"Build me an agent that…"
People do not arrive at a directory with a slug in mind. They arrive with a sentence: *a Base trading agent that swaps USDC to ETH on a signal*. Turning that sentence into a build has meant reading a catalogue, guessing at a stack, and discovering the install path was stale three commands in.
Sato Bot takes the sentence and returns a plan. It is MCP tool #25,
onchain_agent_build_plan, on the server at https://satohub.ai/api/mcp, and
GET /api/satobot/plan over plain HTTP.
There is no model in the brain
That is the design, not a limitation. buildPlan() is deterministic: intent
and chain come from small rule tables, and everything else is produced by
library functions that already exist and already publish their own rules. It
composes recommend_stack, the deploy spec off each listing record,
[Preflight](https://satohub.ai/preflight) for the verdicts, and
[Sato Route](https://satohub.ai/route) for the first action — every one called
as a function, in one process, against one set of records. No self-fetch, no
second opinion that can disagree with the first.
The consequence worth stating: it cannot invent a listing. A component that is not in the directory cannot appear in a plan. Names, scores, URLs and specs all come from the record, and a record that is empty produces "the record is empty", which is an answer.
What a plan contains
``
restatement : You want: a Base trading agent that swaps USDC to ETH on a
signal. Chain: Base. Read as a swap build.
intent : swap (chain_source: given)
stack : framework almanak (Sato Score 83, preflight go)
wallet privy (83, go) · trading 1inch (75, go) · …
first_action: swap, ready:false — missing "a live quote — re-run the route for
your own size"
open_qs : Who holds the keys, and what is the agent allowed to sign without
you? · What triggers a trade, what size, and what happens when
the signal is wrong?
``
Each stack item carries its Sato Score, liveness, the observed record of our
own daily checks, its sato_url, the
[deploy spec](https://satohub.ai/docs/deploy-spec) when the listing publishes
one, and a Preflight verdict. Then the gaps — spelled out rather than papered
over — the questions the user still has to answer, and the next steps, which
include gathering the keys and endpoints the stack needs *before* wiring
anything.
The open questions are half the value. A plan that does not ask who holds the keys is not a plan.
Nothing in it is custodial
Sato Bot holds no keys, signs nothing, deploys nothing, moves nothing.
A swap first action is quoted at a nominal size — one unit of the input token — purely so the route can be read. Your real size is yours to choose, and you re-quote for it. A launch first action is a config you read and sign with your own signer, with the fee disclosed before you sign. Both say so in the payload, in words.
A Preflight that fails or runs out of time becomes verdict: "unknown" with
the reason attached — not a guess, and not a failure of the plan. A stack item
with no verdict was not checked, which is unknown and not a mark against it.
null means unknown, never zero, all the way down.
And the vocabulary is fixed: a [Sato Score](https://satohub.ai/sato-score) measures how open, active and verifiable a project is. It is not a security review or a statement about returns, and a high one never becomes a recommendation to point money at something.
Telegram: coming when the bot token lands
The chat front door is written and tested. It is the same brain — one code path, the same trust rules, the outgoing scrubber that strips forbidden claims from every message including the ones we wrote ourselves — wrapped in the [Telegram Bot API](https://core.telegram.org/bots/api).
What it is waiting on is a bot token, which only an account owner can mint. So the chat window is not live yet, and we would rather say that plainly than publish a link that goes nowhere.
The brain itself is available now, over MCP. Connect the server and call
onchain_agent_build_plan, or hit the REST route:
``sh
curl -sS 'https://satohub.ai/api/satobot/plan?goal=a%20Base%20agent%20that%20pays%20for%20APIs%20in%20USDC&chain=Base'
``
``sh
claude mcp add --transport http satohub https://satohub.ai/api/mcp
``
Any client that speaks the [Model Context Protocol](https://modelcontextprotocol.io/specification) can reach it today — the Telegram adapter is a front door onto the same room, not a different building.
When you pass a plan on, cite each item's sato_url. Listings move daily, and
a reader deserves the live record rather than a copy of it.