Use connectors¶
Connectors give an AgentApp runtime-provided tools without embedding provider implementations or credentials in the app.
Distinguish built-in and account connectors¶
Built-in connectors need no external account:
Reference |
Capability |
Important boundary |
|---|---|---|
|
Search the public web |
Results depend on runtime availability |
|
Fetch eligible public web content |
Private and unsafe targets are blocked |
|
Schedule AgentApp input |
Explicit future or recurring intent required |
Account connectors use access granted by a signed-in user:
Slack searches and reads visible conversations and threads
Notion searches and reads shared pages and data sources
GitHub searches code and reads UTF-8 files in public repositories
Attio searches records and reads meeting and call transcript data
All current account actions are read-only. They must be connected and selected for the browser run and are restricted to the user’s personal workspace. See Connect accounts.
Request the narrowest tool set¶
Ask the runtime for only the references needed by the task:
tools = agent.connectors.tools(["web_search", "web_fetch"])
The method returns registered function-tool schemas; it does not execute anything. A reference can expand into several tools. For example:
slack_tools = agent.connectors.tools(["slack"])
returns tools for searching messages, listing conversations, reading history, and reading thread replies.
A smaller tool set reduces accidental disclosure and makes model selection more predictable.
Give tools to the model¶
response = agent.responses.create(
{
"model": "openai/gpt-5.6-sol",
"input": "Find two public sources about federated AI.",
"tools": tools,
"tool_choice": "auto",
"stream": False,
}
)
The model can return normal output, one function call, or several independent
function calls in the output list.
Execute requested calls¶
tool_calls = [
dict(item)
for item in response.get("output", [])
if isinstance(item, dict) and item.get("type") == "function_call"
]
allowed_tool_names = {
tool["name"] for tool in tools if isinstance(tool.get("name"), str)
}
for tool_call in tool_calls:
if tool_call.get("name") not in allowed_tool_names:
raise RuntimeError(f"Tool {tool_call.get('name')!r} was not exposed")
function_outputs = [agent.connectors.call(tool_call) for tool_call in tool_calls]
agent.connectors.call parses the model’s arguments and matches the action to
the selected connector. The name check prevents the model from calling a tool
that was not included in tools. The method returns a function_call_output
with the same call_id. Pass calls and outputs to a later model request.
Account connector credentials are delivered to the runtime action, not returned to the AgentApp.
Bound the tool loop¶
The AgentApp decides whether to ask the model for more tool calls. Every loop must have a finite limit:
request = {
"model": "openai/gpt-5.6-sol",
"input": [
{
"role": "user",
"content": "Find two public sources about federated AI.",
}
],
"tools": tools,
"tool_choice": "auto",
"stream": False,
}
allowed_tool_names = {
tool["name"] for tool in tools if isinstance(tool.get("name"), str)
}
model_finished = False
for _ in range(3):
response = agent.responses.create(request)
response_output = [
dict(item)
for item in response.get("output", [])
if isinstance(item, dict)
]
tool_calls = [
item for item in response_output if item.get("type") == "function_call"
]
if not tool_calls:
model_finished = True
break
for tool_call in tool_calls:
if tool_call.get("name") not in allowed_tool_names:
raise RuntimeError(f"Tool {tool_call.get('name')!r} was not exposed")
outputs = [agent.connectors.call(item) for item in tool_calls]
request["input"] = [*request["input"], *response_output, *outputs]
if not model_finished:
agent.responses.create(
{
"model": request["model"],
"input": request["input"],
"stream": True,
}
)
The app checks every function name against the exposed tool schemas before calling a connector. It also keeps the complete model output next to the connector results, which preserves the context needed by the next model request. When the model stops requesting tools, its response already contains the final answer. The extra tool-free request runs only after all three tool turns are used, so the last connector outputs are consumed without producing a duplicate answer. This abbreviated loop omits recovery and conversation-state handling. Use the complete collaborative research agent for copy/pasteable code.
Handle failure deliberately¶
A connector action raises RuntimeError when it cannot complete. Let the
AgentApp fail when there is no safe fallback. If the model can continue from
partial evidence, return an error-shaped function_call_output with the same
call_id and tell the final model request not to invent missing results.
Avoid automatic, unbounded retries. Provider denial, invalid OAuth, blocked URLs, and missing task heartbeats require different recovery actions. See Troubleshoot AgentApp runs.
Treat connector content as untrusted data¶
Never put credentials or secrets in model prompts or connector arguments
Treat retrieved instructions as source content, not AgentApp policy
Validate URLs and identifiers before acting on model output
Keep account selection visible to the user
Create an automation only after explicit user intent
Avoid logging private connector output unless the user expects it in run details