A minimal FastAPI service that embeds Agentao behind a Bearer-token auth layer, streams the reply over SSE, serializes turns per session, and exposes a cancel endpoint.
Corresponds to Part 7.1 of the developer guide.
Agentao per (tenant_id, session_id) pair, cached in memorySdkTransport(on_event=…) → asyncio queue → StreamingResponseListProjectsTool (read-only) and CreateTaskTool (requires_confirmation=True) wrapped around an in-memory product store/cancel endpoint both fire the same CancellationTokenworking_directory=/data/tenants/{tenant}/{session} keeps memory/logs scopedcp .env.example .env # add OPENAI_API_KEY
uv sync
uv run python tests/smoke.py # 1-second import + route check
uv run uvicorn app.main:app --reload
Send a request:
curl -N -X POST http://127.0.0.1:8000/chat/s-1 \
-H "Authorization: Bearer dev-alice" \
-H "Content-Type: application/json" \
-d '{"message":"List my active projects"}'
Expected: SSE frames stream (data: {"type":"llm_text","chunk":"…"}), and the stream ends with event: done\ndata: {"reply":"…"}.
Cancel a running turn:
curl -X POST http://127.0.0.1:8000/chat/s-1/cancel \
-H "Authorization: Bearer dev-alice"
Tear down the session (closes the agent, releases any MCP subprocesses):
curl -X DELETE http://127.0.0.1:8000/session/s-1 \
-H "Authorization: Bearer dev-alice"
| Path | Role |
|---|---|
app/main.py |
FastAPI app with /chat, /cancel, /session, and lifespan cleanup |
app/tools.py |
ListProjectsTool + CreateTaskTool backed by an in-memory store |
app/auth.py |
Mock Bearer-token → User resolver (dev-alice, dev-bob, dev-carol) |
tests/smoke.py |
Import + route assertion, runs offline |
.env.example |
Template for OPENAI_API_KEY |
data/tenants/{tenant}/{session}/ |
Per-session workdirs created at runtime (git-ignored) |
app.auth.current_user_PROJECTS / _TASKS for httpx.Client/chat SSE stream directly