The gap between "found it" and "ran it"
An agent that can search a directory can also npm install the first thing it
finds, open an MCP endpoint it has never seen, pay an address another agent
handed it, or call an ERC-20 whose contract nobody read. The lookup step got
cheap. The step between the lookup and the action did not exist.
Preflight is that step. One call, one target, one verdict:
``
GET https://satohub.ai/api/preflight?repo=coinbase/agentkit
``
or, over MCP, onchain_agent_preflight — tool #21 on the server at
https://satohub.ai/api/mcp.
What comes back
A verdict — go, caution, no, or unknown — the id of the rule that
decided it, and one evidence line per check. Every line names the field it was
read from and the date that field was written:
``json
{
"verdict": "go",
"rule": "R5",
"target": { "kind": "repo", "slug": "coinbase-agentkit",
"sato_url": "https://satohub.ai/resources/coinbase-agentkit" },
"evidence": [
{ "check": "Sato Score", "result": "88 of 100, tier High. The score measures how open, active and verifiable the project is, not safety or quality.",
"source_field": "resources.trust_score", "checked_at": "2026-09-12" },
{ "check": "Reproduced install", "result": "The documented install path was re-run in an isolated container and completed. Proves installability, not runtime behaviour.",
"source_field": "resources.deploy_spec.deploy_status", "checked_at": "2026-09-07" }
]
}
``
Five target kinds, one per call: a GitHub repo, an npm or PyPI package, an
MCP endpoint, an agent as <chain>:<id> under
[ERC-8004](https://eips.ethereum.org/EIPS/eip-8004), or a token address plus
its chain.
An endpoint that is not in the directory gets exactly one live handshake —
initialize plus tools/list under the
[MCP specification](https://modelcontextprotocol.io/specification), capped at
eight seconds — and it can never come back go. A handshake is not a record.
The token lane
Point it at an ERC-20 on Base, Ethereum or Arbitrum and it reads the chain
directly, with no key and no paid RPC: bytecode presence and size, the ERC-20
views, the [Clanker v4](https://clanker.gitbook.io/documentation/sdk-reference/v4)
factory's own deployment record via tokenDeploymentInfo — the factory's
ledger, not a bytecode guess — and the Uniswap v3 factory across the four
standard fee tiers against wrapped native.
The interesting part is what it refuses to answer.
Holder concentration is permanently null. There is no keyless public source for it, and scraping an explorer's HTML is not a method worth citing. The evidence line says so rather than leaving a silent gap where a reader would assume a zero.
Uniswap v4 and non-Uniswap liquidity are permanently null. A v4 pool lives in a singleton PoolManager addressed by a [poolId derived from a PoolKey](https://docs.uniswap.org/contracts/v4/concepts/pool-id) — currency pair, fee, tick spacing, hook — and that key cannot be reconstructed from a token address alone. Any v4 answer would be a guess wearing the costume of a reading.
And a pool existing is existence, not depth. No reserves, no TVL, no price.
What a verdict is not
It is not a security review. It is not an audit, a token screen, or a forecast.
Nothing in the token lane says rug or scam, because those are conclusions and
this returns readings. A null means unknown and never zero, and each null
carries the reason it is null.
unknown is the one worth internalising: it means Sato Hub holds no record of
this target. It does not mean something is wrong with it. An honest blank beats
a confident guess every time — which is also why an unlisted endpoint's single
handshake tops out at caution.
The [Sato Score](https://satohub.ai/sato-score) that appears in the evidence
measures how open, active and verifiable a project is. It has never been a
safety or quality grade, and reading one into a go would undo the point of
publishing the components.
Use it
```sh # REST curl -sS 'https://satohub.ai/api/preflight?package=solana-agent-kit' curl -sS 'https://satohub.ai/api/preflight?agent=base:42'
# MCP curl -sS https://satohub.ai/api/mcp \ -H 'Content-Type: application/json' \ -H 'Accept: application/json, text/event-stream' \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{ "name":"onchain_agent_preflight", "arguments":{"token":"0x1bc0c42215582d5A085795f4baDbaC3ff36d1Bcb","chain":"Base"}}}' ```
The verdict engine is pure — the HTTP lane and the MCP lane call the same function, so the two cannot drift and answer differently. Keyless, read-only, and it never signs, holds a key or moves anything.
The human-readable version, including the rule table, is at [satohub.ai/preflight](https://satohub.ai/preflight).