-
Notifications
You must be signed in to change notification settings - Fork 3
docs: add AgentSystems Notary integration #38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
brandon-agsys
wants to merge
2
commits into
agentcontrol:main
Choose a base branch
from
brandon-agsys:docs/add-agentsystems-notary
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 1 commit
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,112 @@ | ||
| --- | ||
| title: AgentSystems Notary | ||
| description: Tamper-evident audit trails for Agent Control events. | ||
| --- | ||
|
|
||
| AgentSystems Notary writes every Agent Control event to independent, tamper-evident storage — so you can prove to auditors, regulators, and customers exactly which controls fired, when, and what they decided. | ||
|
|
||
| ## How it works | ||
|
|
||
| Raw event payloads stay in your own S3 bucket. A SHA-256 hash of each event is written to the Arweave permaweb (or managed WORM storage). Auditors re-hash the raw payloads and compare them against the stored hashes — matching hashes prove integrity, mismatches expose tampering. | ||
|
|
||
| ## Storage options | ||
|
|
||
| | Option | Best for | What you get | | ||
| |--------|----------|--------------| | ||
| | **Arweave (Decentralized)** | No vendor lock-in | Public append-only ledger, open-source verification, no account required | | ||
| | **Custodied** | Managed compliance | Write-once storage, verification UI, signed attestation PDFs | | ||
|
|
||
| ## Setup | ||
|
|
||
| Notary integrates as a control event sink. Works with any framework Agent Control supports — LangChain, CrewAI, Google ADK, AWS Strands. | ||
|
|
||
| ### Prerequisites | ||
|
|
||
| - A running Agent Control server with at least one agent and one control configured (see the [Quickstart](/core/quickstart)) | ||
| - An S3 bucket for raw event payloads | ||
| - A hash storage backend — either an Arweave signing key (decentralized) or an AgentSystems API key (custodied). See the [Notary docs](https://docs.agentsystems.ai/notary) for setup. | ||
|
|
||
| ### Install and register the sink | ||
|
|
||
| ```bash | ||
| pip install 'agentsystems-notary[agent-control]' | ||
| ``` | ||
|
|
||
| The example below uses Arweave. To use the custodied service instead, swap `ArweaveHashStorage` for `CustodiedHashStorage(api_key=..., slug=...)` — see the [Notary docs](https://docs.agentsystems.ai/notary) for the custodied setup. | ||
|
|
||
| ```python | ||
| import os | ||
|
|
||
| from agent_control.observability import register_control_event_sink | ||
| from agentsystems_notary import ( | ||
| AgentControlNotarySink, | ||
| ArweaveHashStorage, | ||
| AwsS3StorageConfig, | ||
| LocalKeySignerConfig, | ||
| NotaryCore, | ||
| RawPayloadStorage, | ||
| ) | ||
|
|
||
| notary = NotaryCore( | ||
| raw_payload_storage=RawPayloadStorage( | ||
| storage=AwsS3StorageConfig( | ||
| bucket_name=os.environ["ORG_AWS_S3_BUCKET_NAME"], | ||
| aws_access_key_id=os.environ["ORG_AWS_S3_ACCESS_KEY_ID"], | ||
| aws_secret_access_key=os.environ["ORG_AWS_S3_SECRET_ACCESS_KEY"], | ||
| aws_region=os.environ["ORG_AWS_S3_REGION"], | ||
| ), | ||
| ), | ||
| hash_storage=[ | ||
| ArweaveHashStorage( | ||
| namespace="my-agent-namespace", # scopes your stored data | ||
| signer=LocalKeySignerConfig( | ||
| private_key_path=os.environ["ARWEAVE_PRIVATE_KEY_PATH"], | ||
| ), | ||
| ) | ||
| ], | ||
| ) | ||
|
|
||
| register_control_event_sink(AgentControlNotarySink(notary)) | ||
| ``` | ||
|
|
||
| Once the sink is registered, every control your agents trigger is automatically notarized — no changes to your `@control()` decorators or control definitions required. | ||
|
|
||
| <Note> | ||
| Agent Control's event batcher flushes sink events asynchronously. In short-lived scripts, allow a few seconds for events to flush before exiting (e.g. `await asyncio.sleep(5)`). Long-running agents don't need this. | ||
| </Note> | ||
|
|
||
| ## What gets notarized | ||
|
|
||
| Each event becomes a canonical JSON record, hashed and pinned to your chosen hash storage. The `pre_execution_record` includes the full Agent Control event — `control_name`, `evaluator_name`, `action`, `matched`, `confidence`, `trace_id`, `span_id`, and the `condition_trace` showing exactly which pattern or rule matched: | ||
|
|
||
| ```json | ||
| { | ||
| "metadata": { "session_id": "...", "sequence": 1, "timestamp": "..." }, | ||
| "input": { "selector_path": "output", "check_stage": "post" }, | ||
| "output": { "matched": true, "action": "deny" }, | ||
| "pre_execution_record": { | ||
| "control_name": "block-ssn", | ||
| "evaluator_name": "regex", | ||
| "action": "deny", | ||
| "matched": true, | ||
| "confidence": 1, | ||
| "agent_name": "my-agent", | ||
| "trace_id": "...", | ||
| "span_id": "...", | ||
| "metadata": { | ||
| "pattern": "\\b\\d{3}-\\d{2}-\\d{4}\\b", | ||
| "condition_trace": { "matched": true, "message": "Pattern found", "...": "..." } | ||
| }, | ||
| "timestamp": "..." | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ## Verification | ||
|
|
||
| Download raw payloads from your S3 bucket, re-hash them, and compare against the stored hashes. Use the [Verify UI](https://verify.agentsystems.ai) for a one-click verification flow, or the open-source [`agentsystems-verify` CLI](https://github.com/agentsystems/agentsystems-verify) for programmatic verification. | ||
|
|
||
| ## Resources | ||
|
|
||
| - [AgentSystems Notary on PyPI](https://pypi.org/project/agentsystems-notary/) | ||
| - [Source on GitHub](https://github.com/agentsystems/agentsystems-notary) | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This appears to change the hashing source from raw payload bytes to canonical JSON. Please clarify which bytes are actually hashed so the verification instructions stay accurate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, @namrataghadi-galileo - the doc was conflating "Agent Control event" with "Notary record."
To clarify: Agent Control events are consumed as a Python dict via
event.model_dump()and embedded as thepre_execution_recordfield of a Notary record (alongside metadata, input, output). The Notary record is what gets JCS-canonicalized (RFC 8785) and SHA-256 hashed - so however you evolveControlExecutionEvent, Notary's hashing handles it deterministically and past hashes remain verifiable. Verification issha256(stored_bytes)against the stored hash.Updated the relevant sections in the latest commit. Thanks!