Connect Blazing Agents to your app
Add a chat endpoint to your backend that checks who the user is, streams the answer, and remembers each conversation.
Add one chat endpoint to your backend. It checks who the user is, sends their message to your agent, and streams the answer back. Blazing Agents keeps the conversation history, so your endpoint only has to remember which user owns which conversation.
Before you begin
Finish Run your first agent and keep the same project folder and terminal. Set the agent ID it printed, and a demo token that stands in for your own sign-in:
export BLAZING_AGENTS_AGENT_ID="ag_..."
export DEMO_USER_TOKEN="demo-token"Keep credentials on the backend
Your browser or mobile app talks only to your backend. It never receives the Blazing Agents API key.
Put your backend between users and Blazing Agents
Install a small web framework for the endpoint:
npm install hono @hono/node-serverYour backend does three things on every request: it signs the user in, checks that they own the conversation they ask for, and calls Blazing Agents with your API key.
Add a chat endpoint
Save this as server.ts or server.py. The users and owners dictionaries stand in for your sign-in and your database.
import { serve } from "@hono/node-server";
import { BlazingAgents, createChatRelay } from "@blazingagents/sdk";
import { Hono } from "hono";
const client = new BlazingAgents({
apiKey: process.env.BLAZING_AGENTS_API_KEY!,
});
// Replace these with your own sign-in check and database.
const users = new Map([[process.env.DEMO_USER_TOKEN!, "user-1"]]);
const owners = new Map<string, string>();
const relayChat = createChatRelay({
client,
async resolveContext(request) {
const token = request.headers.get("authorization")?.replace("Bearer ", "");
const userId = token ? users.get(token) : undefined;
return userId
? { agentId: process.env.BLAZING_AGENTS_AGENT_ID!, userId }
: null;
},
sessions: {
async ownerOf(sessionId) {
return owners.get(sessionId);
},
async recordOwner(sessionId, userId) {
owners.set(sessionId, userId);
},
},
});
const app = new Hono();
app.post("/api/chat", (c) => relayChat(c.req.raw));
serve({ fetch: app.fetch, port: 8787 });Start it with node server.ts or uvicorn server:app --port 8787.
Verify the integration
In a second terminal, export DEMO_USER_TOKEN again and ask the agent to remember something:
curl -i -N http://localhost:8787/api/chat \
-H "authorization: Bearer $DEMO_USER_TOKEN" \
-H "content-type: application/json" \
-d '{"message":{"id":"m1","role":"user","parts":[{"type":"text","text":"Remember the word cobalt."}]}}'The answer streams in as data: {...} lines. Among the response headers is a location header that ends in the new ss_... session ID. Send it back with a follow-up question:
curl -N http://localhost:8787/api/chat \
-H "authorization: Bearer $DEMO_USER_TOKEN" \
-H "content-type: application/json" \
-d '{"sessionId":"ss_...","message":{"id":"m2","role":"user","parts":[{"type":"text","text":"Which word did I ask you to remember?"}]}}'The agent answers "cobalt", because Blazing Agents kept the first exchange. Leave out the authorization header and you get 401. Send a session ID the user does not own and you get 403.
What happened
The first request has no sessionId, so Blazing Agents starts a new session and returns its ID before the answer finishes streaming. Your endpoint records the owner right away, then relays the stream. Later requests send the sessionId, your endpoint checks the owner, and the agent sees the whole conversation. Your frontend sends only the newest message each time.
In TypeScript, createChatRelay does this for you. It also passes the request's abort signal along, so a user who closes the tab stops the turn. The Python endpoint does the same steps by hand with one client.chat() call: it passes session_id only when the request has one, and stream.session_id holds the ID either way.
The userId you pass labels usage and resources per end user for reporting. It does not grant access. Your ownership check is what keeps one user out of another user's conversation.
Production notes
- Replace the demo token with your real sign-in, and the
ownersmap with a database table. - Keep the session ID even when the first turn fails or the user stops it. The conversation exists; it is empty until a turn succeeds.
- Streams must reach the browser unbuffered. The response already sets
Cache-Control: no-cache; make sure every proxy in front of your backend passes the stream through as it arrives.
Next
- Build a chatbot to put a React UI on this endpoint.
- Sessions and turns to reload history and handle busy or failed turns.
- Security and credentials before you go to production.