Skip to main content
This chapter has six steps. Follow them in order.

Step 1 - What you need

You need two things before starting. You may already have them; skim and decide.

Node.js 22+

The gateway is TypeScript; we run it with tsx, no separate build step.

OpenRouter API key

Paid proxy to dozens of models. The gateway uses it for the planner LLM.
Sign up at openrouter.ai, add a few dollars of credit, and copy the key from the API section. It looks like sk-or-v1-<long random string>.
No database required. The gateway is stateless — it holds per-request state in memory for the lifetime of each /plan call and drops it when the call ends. The calling client owns durable history: pass prior turns in the history field and the latest compaction summary in prior_summary on the next call. Old releases required Supabase; that’s gone.

Step 2 - Get the code and install

The uv sync line uses uv, a fast Python package manager. If you don’t have it:

Step 3 - Configure the gateway

Create gateway/.env.local from the template:
Open it in an editor. Fill in:
gateway/.env.local
And examples/.env (used by the sample Python agents - the file already exists, you just add the key):
examples/.env
What’s a “bearer token”?Think of GATEWAY_API_KEY like the password on a movie ticket booth. Whoever holds this string can ask the gateway to do work on their behalf. The gateway checks it on every request by hashing both sides and comparing the hashes in constant time (so neither a timing nor a length attack can recover the token). Don’t paste it into chat apps or commit it to a public repo. Rotate it when you suspect it leaked.
You may notice old SUPABASE_URL / SUPABASE_SERVICE_ROLE_KEY lines in .env.example. Leave them blank — the gateway no longer reads them. See gateway/src/config/loader.ts:110 for the explicit removal note in the code.

Step 4 - Start one agent

Open a terminal. Start the joke agent — one Python file that answers with jokes. We pin the port to 3773 with BINDU_PORT so it matches the next chapter’s fleet layout (the file’s own default is 5773):
The boot prints a block of bindufy setup logs. The last line you should see is:
Leave that terminal running.

Step 5 - Start the gateway

In a second terminal:
Expected output:
The “no DID identity configured” line is expected for now. The DID signing chapter turns on cryptographic signing. session mode: stateless is the only mode in the current gateway — the mode field is kept on the schema for forward-compat but stateful is rejected at boot. Leave this terminal running too.

Step 6 - Ask a question

In a third terminal, load your gateway token into the shell so you don’t have to copy-paste it every time:
Now send the request:
The -N flag tells curl not to buffer - you’ll see output appear one line at a time over about 5 seconds.
Expected stream (a few fields like agent_did, agent_did_source, and signatures are elided for readability — they’re documented in the Gateway API reference):
You made a plan. 🎉

Reading the output line by line

That format is called Server-Sent Events (SSE). It’s plain HTTP, but the server keeps the connection open and writes events one at a time instead of sending one big response at the end. Two parts per event: a label (event: session) and a JSON payload (data: {...}). What each event means, in the order they arrived: You may also see one more event on long conversations:

What’s actually running

You now have three things talking to each other:
The gateway is a coordinator. It doesn’t answer the question itself; it picks an agent, sends the question, gets the reply, writes a final summary using its own planner LLM. It also doesn’t persist anything — when the /plan call ends, the session is gone.
If this is the moment the idea clicks - great. Next we’ll add a second agent so the gateway has a real choice to make: Adding a second agent → Sunflower LogoGateway is stateless - the client owns history.