Files
2026-07-13 12:38:34 +08:00

171 lines
4.4 KiB
Python

"""
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)