Inspiration

AI agents can now open branches, commit code and call models. When one does, you can't tell who allowed it, what it was allowed to touch, or how to stop it halfway through. We wanted every agent action tied to a person who allowed it, with a limit and a record.

What it does

Each agent gets its own verified identity and a time-limited grant from a signed-in human. Every tool call goes through our gateway, which checks the agent's token, the grant, the workflow and the resource before anything runs. If any check fails, the gateway denies the call.

  • A human creates a grant: which agent, which tools, which repository and branch prefix, which models, and an expiry of 4 hours at most.
  • A Lead agent hands smaller grants to a Coder and a Tester. A rogue agent can't delegate from a grant it doesn't hold.
  • Revoke the root grant and the Coder's next call is denied with parent_grant_revoked.
  • The gateway writes every decision to an audit trail before the action runs. If it can't write the record, it denies the call.
  • A Sentinel locks a grant after three violations in a row.
  • Each run ends with a chain you can check: human, token, grant, commit SHA, the test result for that exact SHA, and a pull request a person merged.

How we built it

  • Identity: Amazon Cognito, with one app client per agent and PKCE sign-in for humans through our agentledger CLI.
  • Grants: DynamoDB, with a grant service that enforces roles, expiry and delegation rules. A child grant can only narrow its parent.
  • Gateway: a FastMCP server on EC2, reached through an SSM tunnel. It reads the grant on every call.
  • Actions: a GitHub App for issues, branches, commits, PRs and CI results, and Amazon Bedrock for model calls. Agents never hold a GitHub or AWS credential.
  • Runtime: agentledger run --issue 1 takes an issue to a pull request with three agents. agentledger probe attacks the same workflow with a fourth.
  • Audit: JSON lines per decision and outcome, a timeline, a work-chain report, and a CloudWatch dashboard as a viewing copy.
  • Kiro runs as a single agent through the same gateway on its own workflow.

Challenges we ran into

  • Telling "allowed" apart from "succeeded". We log the decision and the outcome as separate events.
  • Failing closed everywhere. An unreadable grant store, an unwritable audit file or a broken lock file each stop the call.
  • A child grant that left out a limit got a wider default than its parent. Children now inherit the parent's limit.
  • Trusting test results. Tester reads the CI run from GitHub for the exact commit, so the agent's word counts for nothing.

Accomplishments that we're proud of

  • An issue becomes a pull request with passing CI in about 30 seconds.
  • A revoke stopped the Coder's next call in 165 ms.
  • The rogue probe was refused 7 times out of 7, Sentinel lock included.
  • 974 tests passed with live AWS checks on.

What we learned

Most of agent safety comes down to plain rules: check every call, write the record first, deny when unsure. A grant a judge can read in ten seconds beats a clever policy engine.

What's next for Agent Ledger

Signed, tamper-evident audit records. Sentinel state in the grant store instead of a local file. Narrower AWS roles. A live console.

Limits we state up front

  • The gateway controls tool calls that go through it. It can't see a developer's local shell.
  • Agent tokens last 12 hours and can't be revoked early. We revoke grants instead.
  • The audit file is a plain file on the server, so it isn't tamper-proof yet.
  • The EC2 role is broad. This is a hackathon setup, not least privilege.
  • A person merges every pull request. Agents have no merge tool.

Built With

Share this project:

Updates

Submission history