Run Claude
Serve Claude behind your product with streaming responses and saved sessions.
Serve a Claude agent through an HTTP API, stream its response and save its run history. This first service drafts a reply from ticket details supplied in the request. In Connect Your Tools, the agent will fetch those details through MCP.
Set up the service
Use Python 3.12 and an account with access to claude-sonnet-5-5:
mkdir claude_service && cd claude_service
uv venv --python 3.12
source .venv/bin/activate
uv pip install "agno[os]" "claude-agent-sdk==0.2.165"
export ANTHROPIC_API_KEY="your-anthropic-api-key"An existing native CLI login can also authenticate local development. Provision and renew credentials explicitly for a deployed service. The Claude SDK still uses its native runtime and local transcript files.
Create the agent
Save this as harness_service.py:
from pathlib import Path
from agno.agents.claude import ClaudeAgent
from agno.db.sqlite import SqliteDb
from agno.os import AgentOS
workspace = Path("data/claude/workspace").resolve()
workspace.mkdir(parents=True, exist_ok=True)
db = SqliteDb(db_file="data/claude/runs.db")
agent = ClaudeAgent(
id="support-agent",
name="Support Assistant",
model="claude-sonnet-5-5",
db=db,
cwd=str(workspace),
tools=[],
setting_sources=[],
strict_mcp_config=True,
permission_mode="dontAsk",
)
agent_os = AgentOS(agents=[agent], db=db)
app = agent_os.get_app()
if __name__ == "__main__":
agent_os.serve(app=app, host="127.0.0.1", port=7777, reload=False)SQLite keeps this local exercise self-contained. Use Postgres for deployment. The service is bound to loopback and has no caller authentication; Deploy and Operate adds the production configuration.
tools=[] disables built-in tools for this first exercise.
Start and call the API
Start the service:
python harness_service.pyIn another terminal, submit a streamed request:
curl -N http://127.0.0.1:7777/agents/support-agent/runs \
-F 'message=Ticket T-100: the customer asks why order O-100 has not arrived. It shipped yesterday and is due tomorrow. Draft a short reply. Do not use tools.' \
-F 'session_id=support-demo' \
-F 'stream=true'Expect SSE events containing the response, a run ID and a terminal completion event. The answer should use the supplied shipping facts. Copy the run_id from the stream to inspect its saved result:
RUN_ID="paste-the-run-id"
curl "http://127.0.0.1:7777/agents/support-agent/runs/$RUN_ID?session_id=support-demo"The result includes status, content and saved messages. This request needs no tools, so an empty tool list is expected. An error event or ERROR status is not a successful run; check provider authentication and model access before proceeding.
Continue the session
curl -N http://127.0.0.1:7777/agents/support-agent/runs \
-F 'message=Which order were we discussing?' \
-F 'session_id=support-demo' \
-F 'stream=true'Expect the agent to recall O-100. Wait for each turn to finish before submitting the next turn in that session. See Sessions and State for restart and cross-replica behavior.
Next steps
- Connect Your Tools: fetch ticket and order data through MCP.
- Configure Your Agent: instructions, permissions and native options.
- Claude cookbooks: standalone, streaming and session examples.
Add capabilities
- Structured output for validated responses.
- Images and files for attachments and their storage lifecycle.
- Retries for failure handling and idempotent tools.
- Compaction for longer conversations.
- Runs and usage for operational inspection.
- Step replay for checkpoint continuation and forks.