Skip to content

Explore the full Agent SDK surface with a weather agent

The weather agent is the broadest small example in the repository. It fetches live conditions and forecasts, converts units through MCP, writes notes in a session workspace, and pauses an alert tool for human approval. The same agent also runs from HTTP, Slack, a schedule, and the MCP endpoint.

Use this project when you want to see how the Agent SDK's filesystem pieces fit together before you design a larger agent.

Browse the weather agent source.

See the runtime features together

Most examples focus on one architecture. Weather agent puts the major runtime features side by side:

CapabilitySourceRole
Root config and instructionsagent/agent.ts, agent/instructions.mdSelect the cloud runtime and route each request.
Server toolsagent/tools/Execute on the Agent SDK host through authenticated HTTP MCP, fetch Open-Meteo data, call MCP, and model an approval-gated action.
Agent toolsave_weather_note.tsRun a Python script inside the session workspace.
Stdio MCPunits.ts, probe.tsExpose conversion tools to the model, host tools, and channel handlers. Author VM-side probe tools as TypeScript execute functions.
Custom HTTPwebhook.tsStart a turn or call MCP without a model turn.
Slackslack.ts, slack-app.tsCompare account-linked chat with a dedicated app offering approval buttons.
Skill and subagentforecast.md, researcher/Load a procedure on demand or delegate broad research.
Schedule and hookheartbeat.md, audit.tsStart recurring task sessions and observe completed turns.
A/B and evalsagent/ab.ts, evals/Compare a sticky variant and protect tool routing with regression cases.

Follow one request

A current-weather question takes this path:

  1. The built-in HTTP channel, Slack, or the custom /report route creates a durable session.
  2. instructions.md tells the model to call get_weather instead of guessing.
  3. The server tool geocodes the city, fetches Open-Meteo, validates the response, and returns normalized fields.
  4. The agent writes a short answer. The Agent SDK records every event in the session stream.
  5. The audit hook observes turn.completed. If the session joined the A/B experiment, the collector updates its metrics too.

Forecasts route to get_forecast. Unit conversions route to convert_temperature, which calls the units MCP server through ctx.host.mcp. Climate history and broad comparisons route to the researcher subagent.

Prepare the example

You need:

  • Node 22.13 or newer.
  • An agent-runtime credential.
  • Network access to Open-Meteo.
  • Python 3 for save_weather_note.

The project mounts an account-linked Slack channel. The Agent SDK checks the connection at startup, so sign in even when you plan to call a deterministic tool.

The optional approval-enabled Slack app also needs a token pair. agent-sdk slack create --dir examples/weather-agent provisions the app and writes the tokens for you (see the Slack guide); with hand-minted tokens, export them instead:

bash
export WEATHER_AGENT_SLACK_BOT_TOKEN=xoxb-...
export WEATHER_AGENT_SLACK_APP_TOKEN=xapp-...
agent-sdk slack doctor --prefix WEATHER_AGENT

Without those two tokens, the dedicated channel stays idle. The account-linked channel still works.

Inspect before running

bash
agent-sdk validate --dir examples/weather-agent
agent-sdk info --dir examples/weather-agent --json
agent-sdk eval --dir examples/weather-agent --list

The manifest should report eight tools, one skill, two MCP connections, one subagent, three authored channels, one schedule, one hook, and one A/B experiment. The eval listing should report eight cases.

Call the typed tools

Start with the current-weather server tool:

bash
agent-sdk call get_weather \
  --dir examples/weather-agent \
  --input '{"city":"New York City"}'

defineTool gives the input a Zod schema. The Agent SDK validates the JSON before execute runs. The result includes the matched place, condition, temperature, humidity, wind, gusts, and precipitation.

Try the forecast:

bash
agent-sdk call get_forecast \
  --dir examples/weather-agent \
  --input '{"city":"Lisbon","days":5}'

The tool accepts one to seven days. Shared Open-Meteo code lives under agent/lib/, so the Agent SDK imports it without discovering another tool.

Compare server and agent execution

Most weather tools use the default execution: "server". Their TypeScript runs inside the serve host and can reach ctx.host services.

save_weather_note uses execution: "agent" instead. The Agent SDK materializes its script into the agent environment. The script reads JSON from stdin and appends to weather-notes.md in that session's workspace:

bash
agent-sdk run --dir examples/weather-agent \
  --message "Save a note that Boston is cold and windy."

Each session gets its own workspace. Saving a note doesn't edit the authored example.

This split matters on cloud. Server tools execute on the Agent SDK host through an authenticated HTTP MCP endpoint while retaining the active session context. For an agent tool, the Agent SDK includes its catalog and script body in the first prompt; the cloud model writes and invokes the script in its VM.

Verify tool execution on the agent VM

Ask the agent to call probe_cloud_tool on the probe MCP server. agent/mcp-connections/probe.ts authors that tool as TypeScript. The Agent SDK packages it as stdio MCP so a cloud VM with no checkout of this example can still run it. The model lists the server and calls the tool; it does not write a .sh.

A real call writes vm-tool-observations/<id>.json in the agent cwd and returns hostname, cwd, and pid. Stream events show probe:probe_cloud_tool, not shell.

A local .agent-serve/tools/probe_cloud_tool.sh or a marker under probes/ means the model invented a substitute.

bash
agent-sdk run --dir examples/weather-agent \
  --message "Test custom tool execution from this cloud agent. Call probe_cloud_tool."

Use MCP connections in three places

agent/mcp-connections/units.ts starts a local stdio server. The filename makes its server name units. The Agent SDK exposes it to:

  • the model as MCP tools,
  • server tools through ctx.host.mcp, and
  • channel handlers through host.mcp.

probe is a second stdio connection. Its tools are TypeScript execute functions; the Agent SDK packages them so a cloud VM can spawn the server without this checkout. The model calls probe_cloud_tool directly; no host tool wraps it.

convert_temperature demonstrates the server-tool path:

bash
agent-sdk call convert_temperature \
  --dir examples/weather-agent \
  --input '{"value":72,"from":"F"}'

The custom channel demonstrates the handler path. Start the dev server:

bash
agent-sdk dev examples/weather-agent

Then call MCP deterministically through /convert:

bash
curl -s -X POST \
  http://127.0.0.1:3000/weather-agent/v1/channels/webhook/convert \
  -H 'content-type: application/json' \
  -d '{"value":20,"from":"C"}'

No model chooses a tool in this route. The handler calls the MCP server and returns its result.

Keep conversation state in a custom channel

POST /report starts a model turn and waits for it:

bash
curl -s -X POST \
  http://127.0.0.1:3000/weather-agent/v1/channels/webhook/report \
  -H 'content-type: application/json' \
  -d '{"message":"What is the weather in Paris?"}'

The response includes a key. Send it back on the next request to continue the same session:

bash
curl -s -X POST \
  http://127.0.0.1:3000/weather-agent/v1/channels/webhook/report \
  -H 'content-type: application/json' \
  -d '{"message":"How about tomorrow?","key":"<key>"}'

This is the custom-channel version of a continuation token. See webhooks and custom channels for route schemas, authentication, and asynchronous handlers.

Pause a tool for human approval

post_weather_alert sets needsApproval: true. Ask for an ops alert in the playground and the model's tool call parks before execute:

bash
agent-sdk dev examples/weather-agent

Open the printed playground URL, ask:

Alert ops that severe weather is approaching Boston.

Approve or deny the call in the transcript. The dedicated Socket Mode Slack channel can show the same buttons when toolApprovals: true and Slack interactivity are configured.

The example tool returns a placeholder success object. It doesn't contact Slack, PagerDuty, or an ops board. Replace its execute body with your own sink before adapting it.

Use a model turn for this proof. A deterministic agent-sdk call runs the tool body directly and doesn't demonstrate the parked approval flow.

Load procedures and delegate research

The forecast skill gives the root agent an on-demand procedure. The Agent SDK advertises the skill's description, then the harness loads its content when the request matches.

The researcher directory is an SDK subagent. Its description tells the parent when to delegate. It inherits the parent's execution surface, but gets its own instructions:

bash
agent-sdk run --dir examples/weather-agent \
  --message "Compare record summer temperatures across Paris, London, and Rome."

Use a skill when the same agent needs a procedure. Use a subagent when the parent should hand a bounded task to a specialist. The subagents reference explains the current inheritance limits.

Trigger the schedule and inspect the hook

The heartbeat schedule runs at 09:00 UTC on weekdays. Automatic schedule timers stay off under --dev, so dispatch it manually:

bash
curl -s -X POST \
  http://127.0.0.1:3000/weather-agent/v1/dev/schedules/heartbeat

It creates a task session to check San Francisco, New York, and London. The audit hook logs usage after each completed turn. Hooks observe recorded events; their failures don't fail the turn.

Measure variants and regressions

The weather-tool-efficiency A/B experiment assigns sessions by a sticky hash:

  • control returns current conditions in Fahrenheit.
  • treatment adds a brief Celsius instruction and changes get_weather to return Celsius fields.

Samples and aggregate snapshots persist under .agent-serve/. The treatment only changes current conditions; get_forecast still returns Fahrenheit. Treat the branch as an example of ctx.session.abs, not a complete unit policy.

List and run the evals:

bash
agent-sdk eval --dir examples/weather-agent --list
agent-sdk eval --dir examples/weather-agent --json

Five cases cover current weather and forecasts against live Open-Meteo. Three more cover the local MCP converter, the workspace note tool, and the VM-side probe. Together they test model routing, external data, host MCP, agent-side execution, and stdio MCP in the agent environment.

Turn the weather tour into your own agent

Keep the architecture and replace the domain:

  • Swap Open-Meteo tools for your typed service clients.
  • Keep deterministic transforms behind direct server tools or MCP.
  • Use an agent tool only when code must run in the agent workspace.
  • Gate side effects with needsApproval.
  • Put reusable procedures in skills and narrow specialist work into subagents.
  • Add a channel only when the external surface needs its own identity, continuation key, or delivery behavior.

Where to go next