Signing an action and verifying it
Signing turns the bytes of an action into a short signature that only the agent's private key could produce, so anyone with the public key can confirm the action came from that agent and was not changed.
Last updated: 14 Oct, 2026 · Agent Governance Toolkit 4.1.0
The An agent that can prove who it is lesson gave the shop agent a key pair. This lesson uses it. The agent signs the exact bytes of a refund request, and a verifier checks that signature. The point is the contrast: the real request verifies, and a request with one digit changed does not.
Signing the bytes of an action
sign takes bytes and returns a signature as text. verify_signature takes the same bytes and that signature and returns a bool. Both run on the Ed25519 key the identity already holds.
signature = shop.sign(action_bytes) # -> str
ok = shop.verify_signature(action_bytes, signature) # -> boolSigning the refund request and then verifying it twice, once against the real bytes and once against tampered bytes, shows what the signature binds to.
# sign the exact bytes of the action the agent intends to take
action = b"refund order A-2291 amount 40"
signature = shop.sign(action)
# change one digit and the same signature no longer matches
tampered = b"refund order A-2291 amount 9999"
print("verify(correct): ", shop.verify_signature(action, signature))
print("verify(tampered):", shop.verify_signature(tampered, signature))verify(correct): True verify(tampered): False
What the signature is
The signature is a string you can store next to the action or send alongside it. It is a fixed length for this curve, whatever the action, and it is different on every run because the key pair is fresh each time the identity is made.
# the signature is portable text, the same length for any action
print("type :", type(signature).__name__)
print("length:", len(signature))type : str length: 88
Reading the two checks
- The correct bytes verify.
verify_signatureon the exact action that was signed returnsTrue: the public key confirms the private key produced this signature. - The tampered bytes fail. Changing the amount from 40 to 9999 makes
verify_signaturereturnFalse, even though the signature itself is untouched. The signature binds to the bytes. - Nothing was decrypted. A signature is not encryption; the action is still readable. What it adds is proof of who sent it and that it arrived unchanged.
Signing vs sending the action alone
| Action with a signature | Action on its own | |
|---|---|---|
| Proves the sender | Yes, only the private key signs | No, anyone can claim it |
| Catches a changed payload | Yes, verification fails | No, a changed amount looks the same |
| Needs a shared secret | No, the public key verifies | Not applicable |
| Readable by the receiver | Yes, it is not encrypted | Yes |
Where signing an action helps
- A refund or a payment an agent sends downstream, where the receiver must know the amount was not altered in transit.
- A message between two agents, so each can confirm the other sent it.
- An audit record a reviewer might challenge, where a signature ties the logged action to the agent that signed it.
sign takes bytes, not a string. Encode text first with .encode(), and sign the same canonical bytes you verify later. Sign a dict by serialising it the same way both times, or a reordered key will verify as tampered.Related
- Previous: An agent that can prove who it is
- Next: Delegation that cannot escalate
- Reference: Agent Governance Toolkit documentation
- Sign a status request such as
b"order_status A-2291"and verify it comes backTrue. - Verify the refund signature against a second identity's
verify_signatureand watch it fail. - Encode a Python string with
.encode(), sign the bytes, and verify the round trip.
Little by little, you're building something great.