Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

agent-intent-ledger

A local deterministic CLI can record a human-agent intent/action chain and flag narrow classes of drift between an original human request and a later proposed agent action.

This is v0.1.0. It is a small proof, not a framework.

What This Proves

agent-intent-ledger compares three declared JSON inputs:

  • Original human intent.
  • Agent interpreted objective or plan.
  • Proposed agent action.

It emits:

  • A readable terminal report.
  • A machine-readable JSON drift report / receipt.

The CLI does not execute the proposed action. It only evaluates the declared proposal against the declared original intent constraints.

What This Does Not Prove

This does not understand human intent. It compares declared intent constraints against declared agent proposals and flags deterministic mismatch classes.

It does not:

  • Use an LLM in the critical path.
  • Make network calls.
  • Integrate with AgentGate, MCP, or browser automation.
  • Store data in a database.
  • Enforce runtime behavior.
  • Provide a UI.
  • Prevent misalignment.
  • Claim broad human-agent governance coverage.

Relationship To Nearby Projects

  • AgentGate handles after-action accountability: identity, bond, execution record, verification, settlement.
  • ActionProof checks whether a proposed side-effecting JSON intent matches policy.
  • ContextGate checks whether claims or compressed summaries should enter parent context.
  • MemLedger records structured memory claims and memory-use receipts.
  • agent-intent-ledger checks whether a later proposed agent action still traces to the original declared human mandate.

Quickstart

npm install
npm test
npm run typecheck
npm run build

Run the CLI:

npx tsx src/cli.ts evaluate \
  --intent examples/intent-repo-summary.json \
  --plan examples/plan-repo-summary.json \
  --proposal examples/proposal-within-intent.json \
  --json-out .agent-intent-ledger/within-intent-report.json

After npm run build, the package binary points at dist/cli.js:

node dist/cli.js evaluate \
  --intent examples/intent-repo-summary.json \
  --plan examples/plan-repo-summary.json \
  --proposal examples/proposal-within-intent.json \
  --json-out .agent-intent-ledger/within-intent-report.json

Demo Commands

npm run demo:within-intent
npm run demo:drift

Expected demo outputs:

  • npm run demo:within-intent writes .agent-intent-ledger/within-intent-report.json with verdict within_intent.
  • npm run demo:drift writes .agent-intent-ledger/drift-report.json with verdict authority_drift.

The drift demo proposes sending a repo summary to external@example.com even though the original request only allowed reading/listing repo/** and declared no allowed external recipients. The receipt includes all deterministic drift classes found, including authority drift and human reapproval.

Input Files

Intent:

{
  "intent_id": "intent-repo-summary-001",
  "human_request": "Summarize this repo.",
  "allowed_objectives": ["summarize_repository"],
  "allowed_action_types": ["read_file", "list_files"],
  "allowed_resources": ["repo/**"],
  "allowed_external_recipients": [],
  "disallowed_action_types": ["send_email", "delete_file", "modify_file", "post_public"],
  "requires_reapproval_for": ["external_communication", "file_mutation", "credential_access", "public_posting"],
  "created_at": "2026-05-25T00:00:00.000Z"
}

Plan:

{
  "plan_id": "plan-001",
  "intent_id": "intent-repo-summary-001",
  "interpreted_objective": "summarize_repository",
  "planned_steps": [
    {
      "step_id": "step-1",
      "action_type": "list_files",
      "resource": "repo/"
    }
  ],
  "created_at": "2026-05-25T00:01:00.000Z"
}

Proposal:

{
  "proposal_id": "proposal-001",
  "intent_id": "intent-repo-summary-001",
  "plan_id": "plan-001",
  "proposed_action": {
    "action_type": "send_email",
    "objective": "summarize_repository",
    "resource": "external@example.com",
    "recipient": "external@example.com",
    "effect_summary": "Send the repository summary to an external recipient."
  },
  "created_at": "2026-05-25T00:02:00.000Z"
}

Drift Rules

v0.1.0 uses only deterministic checks:

  • objective_drift: proposed objective is not in allowed_objectives.
  • authority_drift: proposed action type is not in allowed_action_types, is explicitly in disallowed_action_types, or declares a recipient not in allowed_external_recipients.
  • resource_drift: proposed resource does not match an allowed resource pattern.
  • requires_human_reapproval: proposed action matches a declared reapproval trigger.
  • scope_drift: chain IDs mismatch, or multiple lower-level drift classes are present.

When multiple drift classes are present, the primary verdict is selected deterministically using this priority:

  1. objective_drift
  2. authority_drift
  3. resource_drift
  4. requires_human_reapproval
  5. scope_drift

The drift_classes array still includes every class found, in stable order.

Resource matching is deliberately simple:

  • Exact string match.
  • Prefix glob only for patterns ending in /**.

For example, repo/** matches repo/README.md and repo/src/index.ts. No complex glob engine is implemented.

Example Drift Report

{
  "schema_version": "0.1.0",
  "receipt_id": "receipt-example",
  "intent_id": "intent-repo-summary-001",
  "plan_id": "plan-001",
  "proposal_id": "proposal-send-email-drift-001",
  "verdict": "authority_drift",
  "drift_classes": [
    "authority_drift",
    "resource_drift",
    "requires_human_reapproval",
    "scope_drift"
  ],
  "reasons": [
    {
      "code": "ACTION_TYPE_NOT_ALLOWED",
      "message": "Proposed action type send_email is not listed in the original intent allowed_action_types."
    },
    {
      "code": "ACTION_TYPE_DISALLOWED",
      "message": "Proposed action type send_email is explicitly disallowed by the original intent."
    },
    {
      "code": "RECIPIENT_NOT_ALLOWED",
      "message": "Proposed recipient external@example.com is not listed in the original intent allowed_external_recipients."
    },
    {
      "code": "RESOURCE_NOT_ALLOWED",
      "message": "Proposed resource external@example.com does not match any original intent allowed_resources pattern."
    },
    {
      "code": "REAPPROVAL_REQUIRED_EXTERNAL_COMMUNICATION",
      "message": "Proposed action matches declared reapproval trigger external_communication."
    },
    {
      "code": "MULTIPLE_DRIFT_CLASSES",
      "message": "Multiple deterministic drift classes were found, so the proposal is also marked as scope drift."
    }
  ],
  "chain": {
    "human_request": "Summarize this repo.",
    "interpreted_objective": "summarize_repository",
    "proposed_action_type": "send_email",
    "proposed_resource": "external@example.com"
  },
  "created_at": "2026-05-25T00:03:00.000Z"
}

Limitations

The tool only compares declared constraints and declared proposals. If those declarations are incomplete, misleading, or wrong, the receipt reflects that declared data. It does not infer true human intent.

Releases

Packages

Contributors

Languages