diff --git a/README.md b/README.md
index 82b5603f..4f92a501 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
-
+
Docs •
Integrations •
- Cookbook •
- Python Client •
- JavaScript Client
-
+ Toolkits •
+ Examples
## What is Arcade AI?
-[Arcade AI](https://arcade-ai.com?ref=github) offers developer-focused tooling and APIs designed to improve the capabilities of LLM applications and agents.
+[Arcade AI](https://arcade-ai.com?ref=github) provides developer-focused tooling and APIs designed to improve the capabilities of LLM applications and agents.
-By providing an authentication and authorization layer for agents and the tools agents use, Arcade AI connects agentic applications with your users' data and services - like accessing their Gmail, GitHub, Zoom, Spotify, LinkedIn, and more.
+By removing the complexity of connecting agentic applications with your users' data and services, Arcade AI enables developers to focus on building their agentic applications.
To learn more, check out our [documentation](https://docs.arcade-ai.com).
-_Pst. hey, you, join our stargazers! It's free!_
+_Pst. hey, you, give us a star if you like it!_
@@ -59,52 +56,52 @@ _Pst. hey, you, join our stargazers! It's free!_
### Requirements
-1. An **[Arcade AI account](https://arcade-ai.typeform.com/early-access)** (current a waitlist)
-2. **Python 3.10+**. Verify your Python version by running `python --version` or `python3 --version` in your terminal
-3. **pip**, the Python package installer that is typically included with Python
+1. An **[Arcade AI account](https://arcade-ai.typeform.com/early-access)** (currently a waitlist)
+2. **Python 3.10+** and **pip**
### Installation
+Install the package:
+
```bash
pip install 'arcade-ai[fastapi]'
```
-Then login to your account (we're working through the waitlist as fast as we can!)
+Log in to your account:
```bash
arcade login
```
-This will open a browser window to login.
+This opens a browser window for authentication.
-### Verify Installation using `arcade chat`
+### Verify Installation with `arcade chat`
-The `arcade-ai` package comes with a CLI app called `arcade chat` that is used to test tools as you develop them.
-
-By default, `arcade chat` will connect to the hosted version of Arcade AI with built-in tools (found in `toolkits`).
+Use the `arcade chat` CLI app to test tools:
```bash
arcade chat
```
-This launches a chat with the Arcade Cloud Engine (hosted at `api.arcade-ai.com`). All pre-built Arcade tools are available to use.
+This connects to the Arcade Cloud Engine (`api.arcade-ai.com`) with all pre-built Arcade tools.
-For example, try asking:
+For example, try:
```
-star the ArcadeAI/arcade-ai repo on Github
+User (dev@arcade-ai.com):
+> star the ArcadeAI/arcade-ai repo on Github
```
-Arcade AI will ask you to authorize with GitHub, and then the AI assistant will star the [ArcadeAI/arcade-ai](https://github.com/ArcadeAI/arcade-ai) repo on your behalf.
+Arcade AI will prompt you to authorize with GitHub and will star the [ArcadeAI/arcade-ai](https://github.com/ArcadeAI/arcade-ai) repo on your behalf.
-You'll see output similar to this:
+You'll see:
```
Assistant (gpt-4o):
I starred the ArcadeAI/arcade-ai repo on Github for you!
```
-You can use Ctrl-C to exit the chat at any time.
+Press `Ctrl-C` to exit the chat.
## Arcade Cloud
@@ -242,6 +239,60 @@ Arcade AI offers a number of prebuilt toolkits that can be used by agents to int
+### Supported Language Models
+
+The LLM API supports a variety of language models. Currently, the ones supported in Arcade Cloud are OpenAI, Anthropic, Ollama, and Groq.
+
+
+
+For more information, refer to the [models documentation](https://docs.arcade-ai.com/integrations/models/openai).
+
### Building Your Own Tools
Learn how to build your own tools by following our [creating a custom toolkit guide](https://docs.arcade-ai.com/tools/overview).
@@ -252,24 +303,10 @@ Arcade AI enables you to evaluate your custom tools to ensure they function corr
Learn how to evaluate your tools by following our [evaluating tools guide](https://docs.arcade-ai.com/home/evaluate-tools/create-an-evaluation-suite).
-### Models
-
-


-
-Arcade AI supports a variety of model providers when using the Arcade AI LLM API.
-
-To see all available models, refer to the [models documentation](https://docs.arcade-ai.com/integrations/models/openai).
-
## Contributing
We love contributions! Please read our [contributing guide](CONTRIBUTING.md) before submitting a pull request. If you'd like to self-host, refer to the [self-hosting documentation](https://docs.arcade-ai.com/home/install/overview).
-## Contributors
-
-
-
-
-
↑ Back to Top ↑
diff --git a/examples/langchain/studio/graph.py b/examples/langchain/studio/graph.py
index 0b558618..b7615178 100644
--- a/examples/langchain/studio/graph.py
+++ b/examples/langchain/studio/graph.py
@@ -1,8 +1,10 @@
import os
-import time
+from datetime import datetime
from configuration import AgentConfigurable
from langchain_arcade import ArcadeToolManager
+from langchain_core.messages import HumanMessage, ToolMessage
+from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langgraph.graph import END, START, MessagesState, StateGraph
from langgraph.prebuilt import ToolNode
@@ -16,54 +18,73 @@ toolkit = ArcadeToolManager(api_key=arcade_api_key)
tools = toolkit.get_tools(langgraph=True)
tool_node = ToolNode(tools)
+PROMPT_TEMPLATE = f"""
+You are a helpful assistant who can use tools to help users with tasks
+Today's date is {datetime.now().strftime("%Y-%m-%d")}
+
+ALL RESPONSES should be in plain text and not markdown.
+"""
+# prompt for the main agent
+prompt = ChatPromptTemplate.from_messages([
+ ("system", PROMPT_TEMPLATE),
+ ("placeholder", "{messages}"),
+])
# Initialize the language model with your OpenAI API key
-model = ChatOpenAI(model="gpt-4o", api_key=openai_api_key)
-# make the model aware of the tools
-model_with_tools = model.bind_tools(tools)
+model = ChatOpenAI(model="gpt-4o", api_key=openai_api_key).bind_tools(tools)
+prompted_model = prompt | model
-# Define the agent function that invokes the model
def call_agent(state):
+ """Define the agent function that invokes the model"""
messages = state["messages"]
- response = model_with_tools.invoke(messages)
- # Return the updated message history
- return {"messages": [*messages, response]}
+ # replace placeholder with messages from state
+ response = prompted_model.invoke({"messages": messages})
+ return {"messages": [response]}
-# Function to determine the next step based on the model's response
-def should_continue(state: MessagesState):
+def should_continue(state: MessagesState, config: dict):
+ """Function to determine the next step based on the model's response"""
last_message = state["messages"][-1]
if last_message.tool_calls:
- tool_name = last_message.tool_calls[0]["name"]
- if toolkit.requires_auth(tool_name):
+ user_id = config["configurable"].get("user_id")
+ tool_name = state["messages"][-1].tool_calls[0]["name"]
+ auth_response = toolkit.authorize(tool_name, user_id)
+ if auth_response.status == "completed":
+ return "tools"
+ else:
# If the tool requires authorization, proceed to the authorization step
return "authorization"
- else:
- # If no authorization is needed, proceed to execute the tool
- return "tools"
# If no tool calls are present, end the workflow
return END
-# Function to handle tool authorization
+def wait_for_auth(state: MessagesState):
+ last_message = state["messages"][-1]
+ if isinstance(last_message, HumanMessage):
+ return "agent"
+ return "tools"
+
+
def authorize(state: MessagesState, config: dict):
+ """Function to handle tool authorization"""
user_id = config["configurable"].get("user_id")
tool_name = state["messages"][-1].tool_calls[0]["name"]
auth_response = toolkit.authorize(tool_name, user_id)
- if auth_response.status == "completed":
- # Authorization is complete; proceed to the next step
- return {"messages": state["messages"]}
- else:
- # Prompt the user to complete authorization
- print("Please authorize the application in your browser:")
- print(auth_response.authorization_url)
- input("Press Enter after completing authorization...")
-
- # Poll for authorization status
- while not toolkit.is_authorized(auth_response.authorization_id):
- time.sleep(3)
- return {"messages": state["messages"]}
+ auth_message = (
+ f"Please authorize the application in your browser:\n\n {auth_response.authorization_url}"
+ )
+ tool_call_id = state["messages"][-1].tool_calls[0]["id"]
+ response = ToolMessage(
+ content=auth_message,
+ tool_call_id=tool_call_id,
+ )
+ # Add the new message to the message history and add a new human message
+ # saying that the agent should try again
+ try_message = HumanMessage(
+ content="Please try the previous tool call again now that you are authorized."
+ )
+ return {"messages": [response, try_message]}
# Build the workflow graph
@@ -73,12 +94,14 @@ workflow = StateGraph(MessagesState, AgentConfigurable)
workflow.add_node("agent", call_agent)
workflow.add_node("tools", tool_node)
workflow.add_node("authorization", authorize)
+# workflow.add_node("wait_for_auth", wait_for_auth)
# Define the edges and control flow
workflow.add_edge(START, "agent")
workflow.add_conditional_edges("agent", should_continue, ["authorization", "tools", END])
-workflow.add_edge("authorization", "tools")
+workflow.add_edge("authorization", "agent")
workflow.add_edge("tools", "agent")
-# Compile the graph
-graph = workflow.compile()
+# Compile the graph with an interrupt after the authorization node
+# so that we can prompt the user to authorize the application
+graph = workflow.compile(interrupt_after=["authorization"])