chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:38:34 +08:00
commit 0549b088a4
2405 changed files with 810255 additions and 0 deletions
+47
View File
@@ -0,0 +1,47 @@
"""
Tool Router - Authorization Example
This example demonstrates how to authorize a toolkit connection
within a Tool Router session.
"""
import os
from composio import Composio
# Initialize Composio
# Set COMPOSIO_API_KEY environment variable or pass api_key parameter
api_key = os.environ.get("COMPOSIO_API_KEY")
if not api_key:
print("Error: COMPOSIO_API_KEY environment variable not set")
print("Please set it using: export COMPOSIO_API_KEY='your_api_key'")
exit(1)
composio = Composio(api_key=api_key)
# Create a tool router session
session = composio.create(
user_id="user_123",
toolkits=["github", "gmail"],
)
print(f"Session created: {session.session_id}")
# Authorize a toolkit connection
# This initiates the OAuth flow and returns a connection request
connection_request = session.authorize("github")
print(f"\nConnection Request ID: {connection_request.id}")
print(f"Status: {connection_request.status}")
print(f"Redirect URL: {connection_request.redirect_url}")
print("\nPlease visit the URL above to authorize the connection.")
# Wait for the user to complete the authorization
# This will poll the API until the connection is active or timeout occurs
try:
connected_account = connection_request.wait_for_connection()
print("\n✅ Connection successful!")
print(f"Connected Account ID: {connected_account.id}")
print(f"Status: {connected_account.status}")
except Exception as e:
print(f"\n❌ Connection failed: {e}")
@@ -0,0 +1,33 @@
import asyncio
from claude_agent_sdk import ClaudeAgentOptions, query
from composio_claude_agent_sdk import ClaudeAgentSDKProvider
from composio import Composio
composio = Composio(provider=ClaudeAgentSDKProvider())
session = composio.create(
user_id="user_123",
)
async def main():
options = ClaudeAgentOptions(
system_prompt="You are an expert Python developer",
permission_mode="bypassPermissions",
mcp_servers={
"composio": {
"type": session.mcp.type,
"url": session.mcp.url,
"headers": session.mcp.headers,
}
},
)
async for message in query(
prompt="Fetch my last email and summarize it.", options=options
):
print(message)
asyncio.run(main())
@@ -0,0 +1,32 @@
from crewai import Agent, Crew, Task
from crewai.mcp import MCPServerHTTP
from composio import Composio
composio = Composio()
session = composio.create(
user_id="user_123",
)
agent = Agent(
role="Gmail agent",
goal="helps with gmail related queries",
backstory="You are a helpful assistant that can use the tools provided to you.",
mcps=[
MCPServerHTTP(
url=session.mcp.url,
headers=session.mcp.headers,
)
],
)
# Define task
task = Task(
description=("Find the last email and summarize it."),
expected_output="A summary of the last email including sender, subject, and key points.",
agent=agent,
)
my_crew = Crew(agents=[agent], tasks=[task])
result = my_crew.kickoff()
print(result)
@@ -0,0 +1,95 @@
"""
Tool Router direct_tools session preset with OpenAI Agents.
SESSION_PRESET_DIRECT_TOOLS is a shortcut for sessions where the full allowed
tool set is known upfront. It loads all tools allowed by the filters directly
into session.tools() and the MCP tool list.
Usage:
COMPOSIO_API_KEY=... OPENAI_API_KEY=... python examples/tool_router/direct_tools_preset.py
"""
import os
from agents import Agent, Runner
from composio_openai_agents import OpenAIAgentsProvider
from pydantic import BaseModel, Field
from composio import Composio, SESSION_PRESET_DIRECT_TOOLS
def require_env(name: str) -> str:
value = os.environ.get(name)
if not value:
raise RuntimeError(f"Set {name} before running this example.")
return value
composio = Composio(
api_key=require_env("COMPOSIO_API_KEY"),
base_url=os.environ.get("COMPOSIO_BASE_URL"),
provider=OpenAIAgentsProvider(),
)
require_env("OPENAI_API_KEY")
class UserNoteInput(BaseModel):
username: str = Field(description="Hacker News username, for example pg")
hn_research = composio.experimental.Toolkit(
slug="HN_RESEARCH",
name="Hacker News research",
description="Internal research notes for Hacker News users.",
)
@hn_research.tool(
slug="GET_USER_NOTE",
name="Get Hacker News user note",
description="Return an internal research note for a Hacker News username.",
)
def get_user_note(input: UserNoteInput, ctx):
username = input.username.lower()
return {
"username": input.username,
"note": (
"Paul Graham; YC co-founder and essayist."
if username == "pg"
else f"No curated internal note for {input.username}."
),
}
session = composio.create(
user_id="direct-tools-example-user",
session_preset=SESSION_PRESET_DIRECT_TOOLS,
toolkits=["hackernews"],
tools={"hackernews": {"enable": ["HACKERNEWS_GET_USER"]}},
experimental={
"custom_toolkits": [hn_research],
},
)
tools = session.tools()
tool_names = [tool.name for tool in tools]
assert "HACKERNEWS_GET_USER" in tool_names
assert "LOCAL_HN_RESEARCH_GET_USER_NOTE" in tool_names
assert "COMPOSIO_SEARCH_TOOLS" not in tool_names
print("Direct tools exposed to the agent:")
for tool in tools:
print(f"- {tool.name}")
agent = Agent(
name="Direct Tools Demo Agent",
instructions="Use the provided tools to perform the task.",
model=os.environ.get("OPENAI_MODEL", "gpt-5.5"),
tools=tools,
)
result = Runner.run_sync(
agent,
'Look up user "pg" on Hacker News and include any internal research note.',
)
print(result.final_output)
+85
View File
@@ -0,0 +1,85 @@
"""
Example demonstrating the Tool Router session files API.
Shows how to list, upload, download, and delete files in a tool router
session's virtual filesystem. Also demonstrates search and execute.
Requires COMPOSIO_API_KEY and OPENAI_API_KEY to be set.
"""
import tempfile
from pathlib import Path
from composio import Composio
from composio_openai import OpenAIProvider
def main():
composio = Composio(provider=OpenAIProvider())
# Create a session
print("Creating tool router session...")
session = composio.tool_router.create(user_id="demo_files_user")
print(f" Session ID: {session.session_id}")
# Upload a file (from bytes)
print("\nUploading file (bytes)...")
remote = session.experimental.files.upload(
b'{"hello": "world"}',
remote_path="test_data.json",
mimetype="application/json",
)
print(f" Uploaded to: {remote.mount_relative_path}")
# List files
print("\nListing files...")
result = session.experimental.files.list(path="/")
print(f" Items: {len(result.items)}")
for item in result.items:
print(f" - {item.mount_relative_path} ({item.size} bytes)")
# Download the file
print("\nDownloading file...")
downloaded = session.experimental.files.download(remote.mount_relative_path)
content = downloaded.text()
print(f" Content: {content[:80]}...")
# Upload from local file
with tempfile.NamedTemporaryFile(mode="w", suffix=".txt", delete=False) as f:
f.write("Hello from local file")
local_path = f.name
try:
print("\nUploading from local path...")
remote2 = session.experimental.files.upload(local_path)
print(f" Uploaded to: {remote2.mount_relative_path}")
finally:
Path(local_path).unlink(missing_ok=True)
# List again
print("\nListing files (after 2nd upload)...")
result2 = session.experimental.files.list(path="/")
print(f" Items: {len(result2.items)}")
for item in result2.items:
print(f" - {item.mount_relative_path} ({item.size} bytes)")
# Delete
print("\nDeleting test files...")
session.experimental.files.delete(remote.mount_relative_path)
session.experimental.files.delete(remote2.mount_relative_path)
print(" Deleted.")
# Search for tools
print("\nSearching for tools...")
search_result = session.search(query="send email")
print(f" Success: {search_result.success}, Results: {len(search_result.results)}")
if search_result.results:
r = search_result.results[0]
print(
f" First result: {r.primary_tool_slugs[:3] if r.primary_tool_slugs else []}"
)
print("\nAll files API operations succeeded.")
if __name__ == "__main__":
main()
@@ -0,0 +1,48 @@
import asyncio
from langchain.agents import create_agent
from langchain_mcp_adapters.client import MultiServerMCPClient
from langchain_openai.chat_models import ChatOpenAI
from composio import Composio
composio = Composio()
session = composio.create(
user_id="user_123",
)
async def main():
try:
mcp_client = MultiServerMCPClient(
{
"composio": {
"transport": "streamable_http",
"url": session.mcp.url,
"headers": session.mcp.headers,
}
}
)
tools = await mcp_client.get_tools()
agent = create_agent(
tools=tools,
model=ChatOpenAI(model="gpt-4o"),
)
result = await agent.ainvoke(
{
"messages": [
{"role": "user", "content": "Fetch my last email and summarize?"}
]
}
)
print(result)
except Exception as e:
print(e)
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,33 @@
from agents import Agent, HostedMCPTool, Runner
from composio import Composio
composio = Composio()
session = composio.create(
user_id="user_123",
)
print(session.mcp)
composio_mcp = HostedMCPTool(
tool_config={
"type": "mcp",
"server_label": "tool_router",
"server_url": session.mcp.url,
"require_approval": "never",
"headers": session.mcp.headers,
}
)
agent = Agent(
name="My Agent",
instructions="You are a helpful assistant that can use the tools provided to you.",
tools=[composio_mcp],
)
result = Runner.run_sync(
starting_agent=agent,
input="Find my last email and summarize it.",
)
print(result.final_output)
+170
View File
@@ -0,0 +1,170 @@
"""
Tool Router preload with OpenAI Agents.
Shows direct tool exposure for:
1. Composio tools via preload["tools"].
2. SDK custom tools via preload=True on the custom tool or toolkit.
3. A nested custom tool override with preload=False inside a preloaded toolkit.
Usage:
COMPOSIO_API_KEY=... OPENAI_API_KEY=... python examples/tool_router/preload.py
"""
import os
from agents import Agent, Runner
from composio_openai_agents import OpenAIAgentsProvider
from pydantic import BaseModel, Field
from composio import Composio
def require_env(name: str) -> str:
value = os.environ.get(name)
if not value:
raise RuntimeError(f"Set {name} before running this example.")
return value
class UserLookupInput(BaseModel):
user_id: str = Field(description="Internal user ID, for example user-1")
class TeamSearchInput(BaseModel):
team: str = Field(description="Team name to search for")
class AccountInput(BaseModel):
user_id: str = Field(description="Internal user ID")
INTERNAL_USERS = {
"user-1": {
"id": "user-1",
"name": "Ada Lovelace",
"email": "ada@example.com",
"team": "platform",
"plan": "enterprise",
},
"user-2": {
"id": "user-2",
"name": "Grace Hopper",
"email": "grace@example.com",
"team": "developer-tools",
"plan": "startup",
},
}
composio = Composio(
api_key=require_env("COMPOSIO_API_KEY"),
base_url=os.environ.get("COMPOSIO_BASE_URL"),
provider=OpenAIAgentsProvider(),
)
require_env("OPENAI_API_KEY")
@composio.experimental.tool(
slug="LOOKUP_INTERNAL_USER",
name="Lookup internal user",
description="Look up an internal demo user profile by user ID.",
preload=True,
)
def lookup_internal_user(input: UserLookupInput, ctx):
user = INTERNAL_USERS.get(input.user_id)
if not user:
raise ValueError(f'User "{input.user_id}" not found')
return user
@composio.experimental.tool(
slug="SEARCH_INTERNAL_USERS",
name="Search internal users",
description=(
"Search demo internal users by team. This custom tool is search-only "
"because preload is not enabled."
),
)
def search_internal_users(input: TeamSearchInput, ctx):
return {
"results": [
user for user in INTERNAL_USERS.values() if user["team"] == input.team
]
}
internal_admin = composio.experimental.Toolkit(
slug="INTERNAL_ADMIN",
name="Internal admin",
description="Demo internal administration tools.",
preload=True,
)
@internal_admin.tool(
slug="GET_ACCOUNT_HEALTH",
name="Get account health",
description="Return internal account health details for a user.",
)
def get_account_health(input: AccountInput, ctx):
return {
"user_id": input.user_id,
"health": "green",
"open_incidents": 0,
"renewal_risk": "low",
}
@internal_admin.tool(
slug="GET_ACCOUNT_AUDIT_LOG",
name="Get account audit log",
description=(
"Return internal account audit events. This overrides the toolkit "
"preload default and remains search-only."
),
preload=False,
)
def get_account_audit_log(input: AccountInput, ctx):
return {
"user_id": input.user_id,
"events": ["login", "settings_viewed"],
}
session = composio.create(
user_id="preload-example-user",
toolkits=["hackernews"],
tools={"hackernews": {"enable": ["HACKERNEWS_GET_USER"]}},
preload={"tools": ["HACKERNEWS_GET_USER"]},
manage_connections=False,
experimental={
"custom_tools": [lookup_internal_user, search_internal_users],
"custom_toolkits": [internal_admin],
},
)
tools = session.tools()
tool_names = [tool.name for tool in tools]
assert "HACKERNEWS_GET_USER" in tool_names
assert "LOCAL_LOOKUP_INTERNAL_USER" in tool_names
assert "LOCAL_INTERNAL_ADMIN_GET_ACCOUNT_HEALTH" in tool_names
assert "LOCAL_SEARCH_INTERNAL_USERS" not in tool_names
assert "LOCAL_INTERNAL_ADMIN_GET_ACCOUNT_AUDIT_LOG" not in tool_names
print("Direct tools exposed to the agent:")
for tool in tools:
print(f"- {tool.name}")
agent = Agent(
name="Preload Demo Agent",
instructions="Use the provided tools to perform the task.",
model=os.environ.get("OPENAI_MODEL", "gpt-5.5"),
tools=tools,
)
prompt = (
'Look up Hacker News user "pg", then look up internal user user-1 and '
"their account health. Summarize the useful facts."
)
result = Runner.run_sync(agent, prompt)
print(result.final_output)
@@ -0,0 +1,47 @@
"""
Tool Router - Session Update Example
Demonstrates using session.update() to modify a session's configuration
after creation — e.g. adding toolkits, changing workbench settings, or
updating preload config without creating a new session.
"""
import os
from composio import Composio
composio = Composio(base_url=os.environ.get("COMPOSIO_BASE_URL"))
# Create a session with gmail only
session = composio.create(
user_id="session-update-demo",
toolkits=["gmail"],
manage_connections=False,
)
print(f"Session created: {session.session_id}")
print(f"Preload: {session.preload}")
# Update: add github toolkit, enable workbench, and preload a tool
session.update(
toolkits={"enable": ["gmail", "github"]},
workbench={"enable": True, "sandbox_size": "medium"},
preload={"tools": ["GITHUB_CREATE_AN_ISSUE"]},
)
print("\nAfter update:")
print(f"Preload: {session.preload}")
# Update: disable workbench entirely
session.update(
workbench={"enable": False},
)
print("\nAfter disabling workbench: done")
# Update: clear manage_connections by passing None
session.update(
manage_connections=None,
)
print("\nAfter clearing manage_connections: done")
@@ -0,0 +1,73 @@
"""
Tool Router - MCP (Model Context Protocol) Example with OpenAI Agents
This example demonstrates how to use Tool Router with MCP servers and OpenAI Agents provider.
The MCP server provides a standardized way to access tools across different platforms,
and OpenAI Agents provider allows you to use these tools with OpenAI's agent framework.
"""
import asyncio
import os
from agents import Agent, HostedMCPTool, Runner
from composio_openai_agents import OpenAIAgentsProvider
from composio import Composio
async def main():
# Initialize Composio with OpenAI Agents provider
# Set COMPOSIO_API_KEY environment variable or pass api_key parameter
api_key = os.environ.get("COMPOSIO_API_KEY")
if not api_key:
print("Error: COMPOSIO_API_KEY environment variable not set")
print("Please set it using: export COMPOSIO_API_KEY='your_api_key'")
return
composio = Composio(api_key=api_key, provider=OpenAIAgentsProvider())
# Create a tool router session
session = composio.create(
user_id="user_123",
toolkits=["github", "gmail"],
)
mcpTool = HostedMCPTool(
tool_config={
"type": "mcp",
"server_label": "tool_router",
"server_url": session.mcp.url,
"require_approval": "never",
"headers": session.mcp.headers,
}
)
print(f"Session created: {session.session_id}")
print(f"MCP Server URL: {session.mcp.url}")
print(f"MCP Server Type: {session.mcp.type}")
# Create an agent with the tools from tool router
agent = Agent(
name="MCP Tool Router Agent",
instructions=(
"You are a helpful assistant that can use GitHub and Gmail tools "
"through the MCP (Model Context Protocol) server. "
"Help users with their GitHub and email tasks."
),
tools=[mcpTool],
)
# Run the agent with a sample task
print("\n--- Running Agent with Tool Router Tools ---")
result = await Runner.run(
starting_agent=agent,
input=(
"List my recent GitHub repositories and tell me about them. "
"If successful, respond with a summary of what you found."
),
)
print(f"\nAgent Result: {result.final_output}")
if __name__ == "__main__":
asyncio.run(main())
+27
View File
@@ -0,0 +1,27 @@
"""
Tool Router - Toolkits Example
This example demonstrates how to retrieve available toolkits
and their connection status in a Tool Router session.
"""
from composio import Composio
composio = Composio()
# Create a tool router session
# When manage_connections is enabled, tools for managing connections are included
session = composio.create(
user_id="pg-test-37ee710c-d5be-4775-91f2-a8e06b937d9b",
manage_connections=True,
)
print(f"Session created: {session.session_id}")
print(f"MCP Server: {session.mcp.url}")
# Get available toolkits for the session
# This returns information about all toolkits available to the user
toolkits = session.toolkits()
print("\nAvailable toolkits:")
print(toolkits)
+91
View File
@@ -0,0 +1,91 @@
"""
Tool Router - OpenAI Agents Example
This example demonstrates how to use Tool Router with OpenAI Agents framework.
OpenAI Agents provides a powerful way to build AI agents that can use tools
and execute complex workflows.
"""
import asyncio
from agents import Agent, Runner
from composio_openai_agents import OpenAIAgentsProvider
from composio import Composio, after_execute, before_execute
from composio.types import ToolExecuteParams, ToolExecutionResponse
async def main():
# Initialize Composio with OpenAI Agents provider
composio = Composio(provider=OpenAIAgentsProvider())
# Create a tool router session for a specific user
# This creates an isolated session with tools for the specified toolkits
session = composio.create(
user_id="user_123",
toolkits=["gmail"],
)
# Define logging modifiers to track tool calls
# Pass empty lists to apply to all tools
@before_execute(tools=[])
def log_before_execute(
tool: str,
toolkit: str,
params: ToolExecuteParams,
) -> ToolExecuteParams:
"""Log tool execution before it runs."""
print(f"🔧 Executing tool: {toolkit}.{tool}")
print(f" Arguments: {params.get('arguments', {})}")
return params
@after_execute(tools=[])
def log_after_execute(
tool: str,
toolkit: str,
response: ToolExecutionResponse,
) -> ToolExecutionResponse:
"""Log tool execution after it completes."""
print(f"✅ Completed tool: {toolkit}.{tool}")
if "data" in response:
print(f" Response data: {response['data']}")
return response
# Get tools wrapped for OpenAI Agents with logging modifiers
# These tools are ready to be used with the OpenAI Agents framework
tools = session.tools(modifiers=[log_before_execute, log_after_execute])
print(f"\nAvailable tools: {len(tools)}")
# Create an agent with the tools from the session
agent = Agent(
name="Gmail Assistant",
instructions=(
"You are a helpful assistant that helps users manage their "
"Gmail accounts. You can check emails, "
"send messages, and perform various actions on the Gmail platform."
),
tools=tools,
)
# Define the task
task = "Fetch my last email from gmail and summarize it"
print(f"\nTask: {task}")
print("\nAgent working...\n")
# Run the agent
result = await Runner.run(
starting_agent=agent,
input=task,
)
# Print the final output
print("\n" + "=" * 50)
print("RESULT:")
print("=" * 50)
print(result.final_output)
if __name__ == "__main__":
asyncio.run(main())