Use connectors¶
Connectors give an AgentApp tools supplied by the runtime 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 = client.responses.create(
model="openai/gpt-5.6-sol",
input="Find two public sources about federated AI.",
tools=tools,
tool_choice="auto",
)
Here, client is the OpenAI client configured with Flower’s injected runtime
URL and credential. See Use the OpenAI SDK in an
AgentApp. The model can return normal
output, one function call, or several independent function calls.
Execute requested calls¶
response_output = [item.to_dict() for item in response.output]
tool_calls = [
item for item in response_output if 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.
A connector result is tool-loop data, not an assistant response, so calling
agent.connectors.call does not display its output as assistant text in Flower
Chat. Normally, pass the result to a final model request and publish that
request’s stream. If the AgentApp intentionally presents connector content
directly, see Publish AgentApp-generated text.
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:
model = "openai/gpt-5.6-sol"
input_items = [
{
"role": "user",
"content": "Find two public sources about federated AI.",
}
]
allowed_tool_names = {
tool["name"] for tool in tools if isinstance(tool.get("name"), str)
}
final_response = None
for _ in range(3):
response = client.responses.create(
model=model,
input=input_items,
tools=tools,
tool_choice="auto",
)
response_output = [item.to_dict() for item in response.output]
tool_calls = [
item for item in response_output if item.get("type") == "function_call"
]
if not tool_calls:
final_response = response
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]
input_items.extend(response_output)
input_items.extend(outputs)
if final_response is None:
final_response = client.responses.create(model=model, input=input_items)
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 answers before the limit, the app reuses that response.
It makes a final request without tools only when all three rounds requested
tools. In both cases, final_response contains the result. This abbreviated
loop omits streaming, error 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