The hosted console
September 3, 2026 · View on GitHub
Everything else in these docs runs on your machine with no account. This page is the other half: streaming a run to app.sponsio.dev so you can see what crossed the boundary, and keeping the rulebook there so a human reviews a rule before it arms.
Enforcement never depends on any of it. The console is where runs are read and rules are reviewed; if the network is down your agent is unaffected.
1. Sign in
Create a key in the console under Setup, then:
sponsio login --key sk_sp_v1_...
It checks the key before saving it to ~/.sponsio/credentials (mode
0600) and prints the projects it can reach.
Confirm what you are pointed at:
sponsio doctor
The Cloud row names the endpoint, the tenant, and every agent that
has a rulebook. If it shows a URL you did not expect, a
previous sponsio login --url ... is still stored and outranks the
default. Log in again with the right --url.
Prefer environment variables in CI: SPONSIO_API_KEY and
SPONSIO_API_URL are read the same way and need no credentials file.
2. Stream a run to the console
This is the step that puts your agent on screen, and it is one line. Attaching a bridge to a guard projects each guarded call into a console step and sends it as the run progresses:
import sponsio
import sponsio.bridge # note: a submodule, import it explicitly
guard = sponsio.Sponsio(config="sponsio.yaml", agent_id="mailer",
mode="enforce")
run = sponsio.bridge.attach(guard)
# ... your agent loop, unchanged ...
run.finish() # flushes the final state
That is all. attach wraps guard_before so every checked call is
recorded; finish() sends the last frame.
Two rules this path is built to respect:
- Sending never blocks the agent. Every upload is best-effort. If the console is unreachable the run is unaffected and the failure is reported at the end, not raised.
- Nothing is invented. A field the run does not carry is left out rather than guessed.
Naming a run
attach generates an id. Pass your own when you want to find it again:
run = sponsio.bridge.attach(guard, session_id="nightly-2026-09-03")
Multi-agent runs
For a single-agent loop the default auto=True records every guarded
call for you. When several agents share one guard, turn it off and
attribute each step yourself:
run = sponsio.bridge.attach(guard, auto=False,
agents=["planner", "writer"])
...
step = run.record(tool_name, args, agent="planner")
agents= takes bare names, or dicts ({"id": ..., "role": ..., "tools": [...]}) when you want roles on the graph.
What does not stream a run
Two things look like they should and do not:
Sponsio(..., dashboard=True)targets a local dashboard on 127.0.0.1, not the cloud.sponsio export-sessions --to <url>ships OTLP spans to the trace store. Those are spans, not runs: they do not appear under Sessions and they carry no contract verdicts.
3. Keep the rulebook in the cloud
Push
sponsio push sponsio.yaml # the path is required
Each agent block becomes the next version of that agent's book.
pushuploads a draft. It does not publish. The version sits unarmed until a human publishes it, which is the point: an agent that can publish its own enforcement rules is one nobody can be held responsible for.pushsays so on its last line.
Publish
Publishing is a human action, in the console: open Rulebook, review
the version, and publish it. There is no sponsio publish command.
List what the key can reach:
sponsio projects # projects, and agents that have a book
That list does not say which books are published. An agent with nothing
but drafts is in it. sponsio pull --agent <name> is what tells you which
head an agent actually has.
Pull
sponsio pull --agent mailer -o sponsio.cloud.yaml
pull returns the published version. A book that has never been
published has no published head to hand out, so you get its latest draft
instead, and the output says so:
wrote sponsio.cloud.yaml · 1 · DRAFT (nothing published yet; publish it to pin what pull returns)
Read that line. Without it you cannot tell whether the rules you just wrote into the file your guard loads were reviewed by anyone.
Pin an exact version when you need to reproduce a run:
sponsio pull --agent mailer --version 46 -o sponsio.v46.yaml
Or let the guard pull for itself
guard = sponsio.Sponsio(config="sponsio://default", agent_id="mailer")
A sponsio://<project> ref resolves to a cloud checkout when a key is
set and the service answers, the last cached copy when it does not, and
a local yaml if you never pulled. Enforcement never waits on the network,
and the run records which version it enforced.
The loop
sponsio login → sign in once
sponsio.bridge.attach() → runs appear under Sessions
sponsio push sponsio.yaml → rulebook uploaded as a draft
(console: Rulebook) → a human reviews and publishes
sponsio pull → the reviewed version comes back
The console's copilot mines proposals from your runs. A proposal is never a rule until someone arms it, and each one states how thin its own evidence is. Read that number before arming.
Related: Install · Write your first contract · CLI reference · Config file