---
meta:
title: Agent frameworks
description: Run your own agent loop on Muse Spark with the Claude Agent SDK or the OpenAI Codex app-server.
keywords: agent frameworks, build an agent, Claude Agent SDK, OpenAI Codex, app-server, agent loop, tool calling
cms:
alias: /model-api/docs/agent-frameworks
target: aidmc
---
# Agent frameworks
Build your own agent on Muse Spark with the framework you already know. Where [coding agents](/docs/coding-agents) give you a ready-made terminal agent, the frameworks here let you write the agent yourself: you define the prompt, the tools, and the control flow, and drive the model loop from your own code.
This guide shows two paths: the [Claude Agent SDK](#claude-agent-sdk), which connects through the [Messages API](/docs/protocols/messages), and the [OpenAI Codex app-server](#codex-app-server), which connects through the OpenAI-compatible [Responses API](/docs/protocols/responses).
## How it works {#how-it-works}
An agent framework owns the loop: it sends your instruction to the model, receives tool-call requests, executes them, feeds the results back, and repeats until the task is done. Muse Spark is the inference backend that decides what to do at each step. You supply three things, the same as any other client:
1. **Base URL**: `https://api.meta.ai/v1`. Both surfaces share it: the Responses API is `/v1/responses` and the Messages API is `/v1/messages`.
2. **API key**: your Model API key (generate one in the [Model API dashboard](/)).
3. **Model ID**: `muse-spark-1.1`.
Which framework to reach for depends on the wire format it speaks:
| Framework | Wire format | Model API surface |
|-----------|-------------|-------------------|
| **Claude Agent SDK** | Anthropic Messages | [Messages API](/docs/protocols/messages) (`/v1/messages`) |
| **OpenAI Codex app-server** | OpenAI Responses | [Responses API](/docs/protocols/responses) (`/v1/responses`) |
Both drive a full agent loop against Muse Spark: file edits, shell commands, tool calls, and multi-step reasoning across turns.
---
## Build with the Claude Agent SDK {#claude-agent-sdk}
The [Claude Agent SDK](https://code.claude.com/docs/en/agent-sdk/overview) is the engine behind Claude Code, exposed as a library for building your own agents. It speaks the Anthropic Messages format, so it connects to Model API through the [Messages API](/docs/protocols/messages).
### Configuration {#claude-agent-sdk-config}
The SDK reads its provider settings from environment variables, the same ones Claude Code uses. Pass them inline through the SDK's `env` option (shown in the [next example](#claude-agent-sdk-code)), or export them before you run:
- **`ANTHROPIC_BASE_URL`**: the Model API base host. The SDK appends `/v1/messages`, so use the bare host with no `/v1` suffix.
- **`ANTHROPIC_AUTH_TOKEN`**: your Model API key. The SDK sends it as `Authorization: Bearer <key>`, which is how Model API authenticates. Use this rather than `ANTHROPIC_API_KEY`, which sends an `x-api-key` header instead.
- **`ANTHROPIC_MODEL`**: the model for the main agent loop.
- **`ANTHROPIC_DEFAULT_OPUS_MODEL`, `ANTHROPIC_DEFAULT_SONNET_MODEL`, `ANTHROPIC_DEFAULT_HAIKU_MODEL`**: the models the SDK resolves when work routes through the `opus`, `sonnet`, or `haiku` alias instead of `ANTHROPIC_MODEL` — subagents can select a tier this way, and `haiku` also backs lightweight background tasks such as summaries and subagent bookkeeping. Point all three at `muse-spark-1.1`, since that's the only model available; otherwise those paths try to reach a Claude model Model API doesn't serve.
- **`CLAUDE_CODE_SUBAGENT_MODEL`**: the model the SDK runs subagents with. Pin it to `muse-spark-1.1` so subagent loops stay on Model API instead of falling back to a Claude model.
### Write the agent {#claude-agent-sdk-code}
The SDK's `query` function runs the loop and streams back messages as the agent works. Configure the tools, permission mode, and system prompt for the job, then read the final answer from the `result` message.
:::tabs
:::tab TypeScript
```typescript title="TypeScript"
import { query } from "@anthropic-ai/claude-agent-sdk";
const run = query({
prompt: "Add input validation to the signup handler and run the tests.",
options: {
model: "muse-spark-1.1",
cwd: "/path/to/workspace",
systemPrompt: "You are a coding agent. Make minimal, well-tested changes.",
allowedTools: ["Read", "Edit", "Bash"],
permissionMode: "bypassPermissions",
settingSources: [],
env: {
...process.env,
ANTHROPIC_BASE_URL: "https://api.meta.ai",
ANTHROPIC_AUTH_TOKEN: process.env.MODEL_API_KEY ?? "",
ANTHROPIC_MODEL: "muse-spark-1.1",
ANTHROPIC_DEFAULT_OPUS_MODEL: "muse-spark-1.1",
ANTHROPIC_DEFAULT_SONNET_MODEL: "muse-spark-1.1",
ANTHROPIC_DEFAULT_HAIKU_MODEL: "muse-spark-1.1",
CLAUDE_CODE_SUBAGENT_MODEL: "muse-spark-1.1",
},
},
});
for await (const message of run) {
if (message.type === "assistant") {
// Stream partial output to your UI as the agent works.
} else if (message.type === "result") {
console.log(message.result); // final answer
console.log(message.usage); // token accounting
}
}
```
:::tab Python
```python title="Python"
import os
import anyio
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage
async def main():
async for message in query(
prompt="Add input validation to the signup handler and run the tests.",
options=ClaudeAgentOptions(
model="muse-spark-1.1",
cwd="/path/to/workspace",
system_prompt="You are a coding agent. Make minimal, well-tested changes.",
allowed_tools=["Read", "Edit", "Bash"],
permission_mode="bypassPermissions",
setting_sources=[],
env={
**os.environ,
"ANTHROPIC_BASE_URL": "https://api.meta.ai",
"ANTHROPIC_AUTH_TOKEN": os.environ["MODEL_API_KEY"],
"ANTHROPIC_MODEL": "muse-spark-1.1",
"ANTHROPIC_DEFAULT_OPUS_MODEL": "muse-spark-1.1",
"ANTHROPIC_DEFAULT_SONNET_MODEL": "muse-spark-1.1",
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "muse-spark-1.1",
"CLAUDE_CODE_SUBAGENT_MODEL": "muse-spark-1.1",
},
),
):
if isinstance(message, ResultMessage):
print(message.result) # final answer
print(message.usage) # token accounting
anyio.run(main)
```
:::
Install with `npm install @anthropic-ai/claude-agent-sdk` (TypeScript) or `pip install claude-agent-sdk` (Python). A few options carry most of the weight:
- **`allowedTools`**: restrict the agent to the tools the task needs. A smaller surface is easier to reason about and cheaper to run.
- **`permissionMode`**: `bypassPermissions` runs unattended without prompting for approval. Only safe inside a sandbox — see [Production patterns](#production-patterns).
- **`settingSources: []`**: don't inherit ambient user or project settings, so runs are hermetic and reproducible.
- **`systemPrompt`**: the agent's operating instructions.
- **`env`**: sets the provider variables in-process, so you don't have to export them globally. Spread the existing environment first, then override the Anthropic keys.
The SDK carries the model's reasoning across tool-call turns over the Messages surface, so Muse Spark keeps the thread of its own thinking through a multi-step loop. See [Reasoning](/docs/reasoning) for how reasoning is carried across turns.
---
## Build with the OpenAI Codex app-server {#codex-app-server}
[OpenAI Codex](https://developers.openai.com/codex/app-server) is a coding agent whose **app-server** exposes the agent over a JSON-RPC protocol on stdio. You run it as a long-lived process and drive it from your own application, embedding Codex's agent loop behind your own interface. It speaks the OpenAI wire format, so it connects to Model API through the [Responses API](/docs/protocols/responses).
### Configuration {#codex-app-server-config}
Register Model API as a custom provider with inline `-c key=value` overrides when you launch the server (shown in the [next example](#codex-app-server-run)). The keys that matter:
- **`model_providers.meta.base_url`**: the OpenAI-compatible base, `https://api.meta.ai/v1` (no trailing slash).
- **`model_providers.meta.env_key`**: the environment variable Codex reads the API key from. Codex sends it as `Authorization: Bearer <key>`. Set `MODEL_API_KEY` in the server's environment.
- **`model_providers.meta.wire_api`**: `responses` targets the [Responses API](/docs/protocols/responses), which carries reasoning across turns for multi-step loops.
- **`model_providers.meta.requires_openai_auth`**: set `false` so Codex authenticates with your API key alone, instead of expecting an OpenAI sign-in.
- **`model` / `model_provider`**: select `muse-spark-1.1` on the `meta` provider as the default.
### Register the model {#codex-model-catalog}
On startup Codex refreshes its model list from the provider's `/v1/models` endpoint and expects a Codex-specific shape. Model API returns the OpenAI-standard list (`{"object":"list","data":[...]}`), so the refresh fails to decode (`missing field 'models'`) and Codex has no model to run. Register the model directly instead.
`-c model_catalog_json` takes the **path** to a JSON catalog file, not the JSON itself. It doesn't have to be a file you keep around: the [example below](#codex-app-server-run) writes the catalog to a temp path at startup and passes that path, so there's nothing to commit.
### Start the app-server {#codex-app-server-run}
Drive the server from your own code. The app-server speaks JSON-RPC over stdin/stdout: spawn `codex app-server`, send `initialize` (then the `initialized` notification), open a thread, and start a turn. The server streams items back as the agent works; the turn is done when a `turn/completed` arrives for your turn id. The provider config and the model catalog ride along as inline `-c` overrides, so there's no config file to manage; the child inherits `MODEL_API_KEY` from your environment.
```javascript title="JavaScript"
import { spawn } from "node:child_process";
import readline from "node:readline";
import { writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
// Register the model so Codex doesn't refresh it from /v1/models (a shape it
// can't decode). Keep the fields that matter to you up top; the rest just
// satisfy Codex's catalog schema, and their defaults are fine as-is.
const modelCatalog = {
models: [
{
// Identity — `slug` must match the `model` you select below.
slug: "muse-spark-1.1",
display_name: "Muse Spark",
description: "Meta Model API model.",
context_window: 1048576,
max_context_window: 1048576,
input_modalities: ["text", "image"],
supports_parallel_tool_calls: true,
// Reasoning effort levels Muse Spark supports.
default_reasoning_level: "xhigh",
supported_reasoning_levels: [
{ effort: "low", description: "Fast responses with lighter reasoning" },
{ effort: "medium", description: "Balanced reasoning" },
{ effort: "high", description: "Greater reasoning depth" },
{ effort: "xhigh", description: "Extra high reasoning depth" },
],
// Base system prompt Codex sends every turn. Swap in your own harness
// instructions for better results.
base_instructions:
"You are a coding agent operating in a terminal. Use the available tools to read and edit files and run shell commands, and complete the user's task with focused, verified changes.",
// Schema housekeeping — Codex expects these; the defaults are fine.
shell_type: "shell_command",
visibility: "list",
supported_in_api: true,
priority: 0,
support_verbosity: true,
default_verbosity: "low",
supports_reasoning_summaries: false,
default_reasoning_summary: "none",
supports_image_detail_original: true,
web_search_tool_type: "text_and_image",
supports_search_tool: false,
truncation_policy: { mode: "tokens", limit: 120000 },
effective_context_window_percent: 95,
additional_speed_tiers: [],
service_tiers: [],
experimental_supported_tools: [],
apply_patch_tool_type: null,
model_messages: null,
availability_nux: null,
upgrade: null,
},
],
};
// Codex reads model_catalog_json as a file path, so write the catalog to a
// temp file and pass that path in the -c overrides below.
const catalogPath = join(tmpdir(), "muse-spark-catalog.json");
writeFileSync(catalogPath, JSON.stringify(modelCatalog, null, 2));
const proc = spawn(
"codex",
[
"app-server",
"-c", 'model="muse-spark-1.1"',
"-c", 'model_reasoning_effort="xhigh"',
"-c", 'model_provider="meta"',
"-c", 'model_providers.meta.name="Meta Model API"',
"-c", 'model_providers.meta.base_url="https://api.meta.ai/v1"',
"-c", 'model_providers.meta.env_key="MODEL_API_KEY"',
"-c", 'model_providers.meta.wire_api="responses"',
"-c", "model_providers.meta.requires_openai_auth=false",
"-c", `model_catalog_json="${catalogPath}"`,
],
{
stdio: ["pipe", "pipe", "inherit"],
// Codex reads the key from env_key (MODEL_API_KEY); export it before running.
env: process.env,
},
);
const rl = readline.createInterface({ input: proc.stdout });
const send = (message) => {
proc.stdin.write(`${JSON.stringify(message)}\n`);
};
let turnId = null;
let finalText = "";
rl.on("line", (line) => {
const msg = JSON.parse(line);
// Thread opened: start a turn.
if (msg.id === 1 && msg.result?.thread?.id) {
send({
method: "turn/start",
id: 2,
params: {
threadId: msg.result.thread.id,
input: [{ type: "text", text: "Summarize this repo." }],
},
});
}
// Turn accepted: remember its id so we complete on the right turn.
if (msg.id === 2 && msg.result?.turn?.id) {
turnId = msg.result.turn.id;
}
// Keep the latest assistant message as items stream in.
if (msg.method === "item/completed" && msg.params?.item?.type === "agentMessage") {
finalText = msg.params.item.text ?? finalText;
}
// Turn finished: confirm it's ours, check status, then stop.
if (msg.method === "turn/completed" && msg.params?.turn?.id === turnId) {
const { status, error } = msg.params.turn;
if (status !== "completed" || !finalText) {
throw new Error(`turn ${status}: ${error?.message ?? "no assistant output"}`);
}
console.log(finalText);
rl.close();
proc.kill();
}
});
send({
method: "initialize",
id: 0,
params: {
clientInfo: { name: "my_product", title: "My Product", version: "0.1.0" },
// Skip high-volume token deltas; act on completed items instead.
capabilities: {
optOutNotificationMethods: [
"item/agentMessage/delta",
"item/reasoning/textDelta",
],
},
},
});
send({ method: "initialized", params: {} });
send({
method: "thread/start",
id: 1,
params: {
model: "muse-spark-1.1",
cwd: process.cwd(),
// Headless: never pause for approval; keep writes inside the workspace.
approvalPolicy: "never",
sandbox: "workspace-write",
},
});
```
A few things make this production-shaped rather than a demo:
- **Register the model.** Codex can't decode Model API's `/v1/models` response, so point it at a [catalog file](#codex-model-catalog) rather than relying on the startup refresh.
- **Completion is an event, not the stream ending.** Match `turn/completed` to the `turn.id` you started (a stream can carry more than one turn), read `turn.status`, and treat a completed turn with no assistant text as a failure.
- **Opt out of token deltas.** Suppress `item/*/delta` notifications and act on `item/completed` instead, unless you're rendering a live typing effect.
- **Run headless deliberately.** `approvalPolicy: "never"` stops Codex pausing for confirmation; pair it with a `sandbox` mode (`workspace-write` keeps edits inside `cwd`) so an unattended agent can't roam. See [Production patterns](#production-patterns).
To point an interactive Codex session at Model API instead, run `codex` with the same `-c` flags.
---
## Production patterns {#production-patterns}
Both frameworks drive a long-running agent subprocess. A handful of patterns separate a reliable production agent from a demo, and they apply whichever framework you pick.
- **Wait for the terminal event.** Completion is the `result` message (Claude Agent SDK) or a `turn/completed` matching your turn id (Codex), not the stream going quiet or the process exiting. Treat a run that finishes without a final message as a failure rather than returning an empty result.
- **Set two timeouts.** Pair an overall wall-clock cap with an idle watchdog that resets on every event. The cap bounds a runaway loop; the watchdog catches a silent hang without cutting off a legitimately long turn.
- **Sandbox unattended agents.** Removing the approval step (`permissionMode: "bypassPermissions"` for the Claude SDK, `approvalPolicy: "never"` for Codex) lets the agent act on its own. Run it inside an OS sandbox with a dedicated per-run working directory and a scrubbed, allowlisted environment. Keep the TLS certificate variables (`SSL_CERT_FILE`, `NODE_EXTRA_CA_CERTS`) in the allowlist so the agent's own HTTPS calls still work.
- **Give the agent only the tools it needs.** Allowlist tools and declare only the MCP servers you trust; don't inherit ambient user or project configuration. A narrow tool surface is safer and cheaper.
- **Meter cost from the final event.** The `result` message carries token `usage`; read it to track spend. See [Pricing and rate limits](/docs/pricing-rate-limits) for the quotas in effect.
- **Retry transient stream errors.** Long turns occasionally hit a dropped stream or a `502`. Retry those with backoff. See [Error handling](/docs/error-handling).
---
## Next steps
Now that your agent is wired up to Muse Spark, take it further:
- Design the tools your agent calls with the [tool calling](/docs/tool-calling) guide, including parallel and forced tool use inside a loop.
- Reach for the [Responses API](/docs/protocols/responses) when you need reasoning to carry across turns in long multi-step sessions.
- Work through the [Cookbook](/docs/cookbook) for end-to-end agentic recipes you can drop into your own harness.
Agent frameworks
Build your own agent on Muse Spark with the framework you already know. Where coding agents give you a ready-made terminal agent, the frameworks here let you write the agent yourself: you define the prompt, the tools, and the control flow, and drive the model loop from your own code.This guide shows two paths: the Claude Agent SDK, which connects through the Messages API, and the OpenAI Codex app-server, which connects through the OpenAI-compatible Responses API.An agent framework owns the loop: it sends your instruction to the model, receives tool-call requests, executes them, feeds the results back, and repeats until the task is done. Muse Spark is the inference backend that decides what to do at each step. You supply three things, the same as any other client:- Base URL:
https://api.meta.ai/v1. Both surfaces share it: the Responses API is /v1/responses and the Messages API is /v1/messages. - API key: your Model API key (generate one in the Model API dashboard).
- Model ID:
muse-spark-1.1.
Which framework to reach for depends on the wire format it speaks:Framework | Wire format | Model API surface |
|---|
Claude Agent SDK | Anthropic Messages | |
OpenAI Codex app-server | OpenAI Responses | |
Both drive a full agent loop against Muse Spark: file edits, shell commands, tool calls, and multi-step reasoning across turns.Build with the Claude Agent SDK
The Claude Agent SDK is the engine behind Claude Code, exposed as a library for building your own agents. It speaks the Anthropic Messages format, so it connects to Model API through the Messages API.The SDK reads its provider settings from environment variables, the same ones Claude Code uses. Pass them inline through the SDK's env option (shown in the next example), or export them before you run:- •
ANTHROPIC_BASE_URL: the Model API base host. The SDK appends /v1/messages, so use the bare host with no /v1 suffix. - •
ANTHROPIC_AUTH_TOKEN: your Model API key. The SDK sends it as Authorization: Bearer <key>, which is how Model API authenticates. Use this rather than ANTHROPIC_API_KEY, which sends an x-api-key header instead. - •
ANTHROPIC_MODEL: the model for the main agent loop. - •
ANTHROPIC_DEFAULT_OPUS_MODEL, ANTHROPIC_DEFAULT_SONNET_MODEL, ANTHROPIC_DEFAULT_HAIKU_MODEL: the models the SDK resolves when work routes through the opus, sonnet, or haiku alias instead of ANTHROPIC_MODEL — subagents can select a tier this way, and haiku also backs lightweight background tasks such as summaries and subagent bookkeeping. Point all three at muse-spark-1.1, since that's the only model available; otherwise those paths try to reach a Claude model Model API doesn't serve. - •
CLAUDE_CODE_SUBAGENT_MODEL: the model the SDK runs subagents with. Pin it to muse-spark-1.1 so subagent loops stay on Model API instead of falling back to a Claude model.
The SDK's query function runs the loop and streams back messages as the agent works. Configure the tools, permission mode, and system prompt for the job, then read the final answer from the result message.Install with npm install @anthropic-ai/claude-agent-sdk (TypeScript) or pip install claude-agent-sdk (Python). A few options carry most of the weight:- •
allowedTools: restrict the agent to the tools the task needs. A smaller surface is easier to reason about and cheaper to run. - •
permissionMode: bypassPermissions runs unattended without prompting for approval. Only safe inside a sandbox — see Production patterns. - •
settingSources: []: don't inherit ambient user or project settings, so runs are hermetic and reproducible. - •
systemPrompt: the agent's operating instructions. - •
env: sets the provider variables in-process, so you don't have to export them globally. Spread the existing environment first, then override the Anthropic keys.
The SDK carries the model's reasoning across tool-call turns over the Messages surface, so Muse Spark keeps the thread of its own thinking through a multi-step loop. See Reasoning for how reasoning is carried across turns.Build with the OpenAI Codex app-server
OpenAI Codex is a coding agent whose app-server exposes the agent over a JSON-RPC protocol on stdio. You run it as a long-lived process and drive it from your own application, embedding Codex's agent loop behind your own interface. It speaks the OpenAI wire format, so it connects to Model API through the Responses API.Register Model API as a custom provider with inline -c key=value overrides when you launch the server (shown in the next example). The keys that matter:- •
model_providers.meta.base_url: the OpenAI-compatible base, https://api.meta.ai/v1 (no trailing slash). - •
model_providers.meta.env_key: the environment variable Codex reads the API key from. Codex sends it as Authorization: Bearer <key>. Set MODEL_API_KEY in the server's environment. - •
model_providers.meta.wire_api: responses targets the Responses API, which carries reasoning across turns for multi-step loops. - •
model_providers.meta.requires_openai_auth: set false so Codex authenticates with your API key alone, instead of expecting an OpenAI sign-in. - •
model / model_provider: select muse-spark-1.1 on the meta provider as the default.
On startup Codex refreshes its model list from the provider's /v1/models endpoint and expects a Codex-specific shape. Model API returns the OpenAI-standard list ({"object":"list","data":[...]}), so the refresh fails to decode (missing field 'models') and Codex has no model to run. Register the model directly instead.-c model_catalog_json takes the path to a JSON catalog file, not the JSON itself. It doesn't have to be a file you keep around: the example below writes the catalog to a temp path at startup and passes that path, so there's nothing to commit.Drive the server from your own code. The app-server speaks JSON-RPC over stdin/stdout: spawn codex app-server, send initialize (then the initialized notification), open a thread, and start a turn. The server streams items back as the agent works; the turn is done when a turn/completed arrives for your turn id. The provider config and the model catalog ride along as inline -c overrides, so there's no config file to manage; the child inherits MODEL_API_KEY from your environment.A few things make this production-shaped rather than a demo:- •Register the model. Codex can't decode Model API's
/v1/models response, so point it at a catalog file rather than relying on the startup refresh. - •Completion is an event, not the stream ending. Match
turn/completed to the turn.id you started (a stream can carry more than one turn), read turn.status, and treat a completed turn with no assistant text as a failure. - •Opt out of token deltas. Suppress
item/*/delta notifications and act on item/completed instead, unless you're rendering a live typing effect. - •Run headless deliberately.
approvalPolicy: "never" stops Codex pausing for confirmation; pair it with a sandbox mode (workspace-write keeps edits inside cwd) so an unattended agent can't roam. See Production patterns.
To point an interactive Codex session at Model API instead, run codex with the same -c flags.Both frameworks drive a long-running agent subprocess. A handful of patterns separate a reliable production agent from a demo, and they apply whichever framework you pick.- •Wait for the terminal event. Completion is the
result message (Claude Agent SDK) or a turn/completed matching your turn id (Codex), not the stream going quiet or the process exiting. Treat a run that finishes without a final message as a failure rather than returning an empty result. - •Set two timeouts. Pair an overall wall-clock cap with an idle watchdog that resets on every event. The cap bounds a runaway loop; the watchdog catches a silent hang without cutting off a legitimately long turn.
- •Sandbox unattended agents. Removing the approval step (
permissionMode: "bypassPermissions" for the Claude SDK, approvalPolicy: "never" for Codex) lets the agent act on its own. Run it inside an OS sandbox with a dedicated per-run working directory and a scrubbed, allowlisted environment. Keep the TLS certificate variables (SSL_CERT_FILE, NODE_EXTRA_CA_CERTS) in the allowlist so the agent's own HTTPS calls still work. - •Give the agent only the tools it needs. Allowlist tools and declare only the MCP servers you trust; don't inherit ambient user or project configuration. A narrow tool surface is safer and cheaper.
- •Meter cost from the final event. The
result message carries token usage; read it to track spend. See Pricing and rate limits for the quotas in effect. - •Retry transient stream errors. Long turns occasionally hit a dropped stream or a
502. Retry those with backoff. See Error handling.
Now that your agent is wired up to Muse Spark, take it further:- •Design the tools your agent calls with the tool calling guide, including parallel and forced tool use inside a loop.
- •Reach for the Responses API when you need reasoning to carry across turns in long multi-step sessions.
- •Work through the Cookbook for end-to-end agentic recipes you can drop into your own harness.