Install the SDK
Anchor one event
Build the anchorer once, when your service starts, and callanchor at the
point where the agent does something you want on the record.
SANNING_SIGNING_SEEDwith 64 lowercase hex characters that your service keeps across restarts.SANNING_API_KEYwith the key from the console.claims-triagewith the name you want this evidence attributed to.
environment: "dev". Production writes to a permanent public
record, so it is a deliberate edit rather than a default you inherit:
Dev and production covers the move.
Enrolment is automatic
Neither SDK needs a registration step, and its absence is not an omission. On the firstanchor call, the SDK proves possession of your signing key to the
control plane, and the agent appears on the console’s fleet under its own key.
One organisation key covers the whole fleet.
Do not write an enrolment call. If you would rather enrol at deploy time,
API keys and scopes shows how to turn the automatic
call off and drive it yourself.
What leaves your process
The content you pass toanchor is hashed where you pass it. Only the hash
travels, inside a signed envelope of a few hundred bytes. Sanning is
content-blind by construction rather than by policy: it never receives the
bytes, so it cannot disclose them. The full boundary is on the
Introduction.
Two consequences reach your code:
recordBytesin TypeScript,record_bytesin Python, are yours to keep. They are whatpayload_hashcommits to, and Sanning never holds them. Configuring a log store, as both samples do, discharges that for you.- A locator binds as your own assertion. Anything you pass as
reforpayloadRefis signed verbatim and published permanently. Keep a bucket path, a tenant id and a person’s name out of both.
The signing seed is the agent’s identity
An agent is its key, not its name. Generate a 32-byte seed once, keep it in the secret store you already run, and load the same seed on every boot:RotationUnauthorizedError.
Event types carry a namespace
claims.decision has two segments, and that is a requirement rather than a
convention. Single-segment names are reserved by the event profile, so an
event type of decision is refused before anything is signed. TypeScript
throws and Python raises InvalidRecordError, both at the call rather than on
the wire.
Name the first segment after your system and the second after what happened.
Close the anchorer before the process exits
close settles every event and reports the ones that were signed and never
delivered. It throws or raises when any remain, because a timeout says nothing
about whether the control plane accepted the envelope.
recordBytes on every gap before anything else. After a failed
delivery they are the only copy of something the control plane may already
hold.
What to read next
Keep what you anchored
The store the hand-over pack reads, and what breaks without it.
Trace a LangChain agent
One handler, every step of a run, instead of a call per step.