Skip to content

fix(examples): parse the canonical EEP gate response in the langgraph agent#65

Open
ucekmez wants to merge 1 commit into
mainfrom
fix/langgraph-example-canonical-402
Open

fix(examples): parse the canonical EEP gate response in the langgraph agent#65
ucekmez wants to merge 1 commit into
mainfrom
fix/langgraph-example-canonical-402

Conversation

@ucekmez

@ucekmez ucekmez commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

Summary

Audit finding (agent-ergonomics vertical): the flagship LangGraph example —
the one place an agent-builder copies from — did not parse the canonical
EEP gate response it advertises. handle_gate_challenge() read a flat
{gate_type, amount, currency} body and split credential/agreement handling
onto 403 by an error string. None of those fields exist in the real
response, so the example would never match a conformant publisher.

Canonical shape

Both 402 access_restricted and 403 access_forbidden
(schemas/v0.1/gate.402-response.json / gate.403-response.json) carry:

{ "error": "access_restricted", "resource": "...", "current_tier": "...",
  "required_tier": "...",
  "unmet_requirements": [ { "type": "payment", "resolution_hint": "Pay $0.10 …", ... } ] }

Every gate type (payment, credential, agreement, identity, …) is an entry in
unmet_requirements, each with a machine-readable resolution_hint.

Change

  • Rewrite the parser to iterate unmet_requirements and build one proof per
    requirement
    , routed on each requirement's type, using the canonical proof
    shapes from @eep-dev/gates (PaymentProof.token, CredentialProof.format,
    agreement signature over document_hash, …). The resolution_hint is what
    lets the agent decide without an LLM — the whole point of the vertical.
  • test_agent.py (5 tests, all passing): payment, multi-requirement,
    403 access_forbidden, non-gate error, and unsatisfiable custom x-*.
  • README + requirements made honest: the example inlines the wire contracts for
    readability and points to eep-gates/eep-signer/eep-validator for
    production, instead of claiming to import packages it never used.

Part of the EEP vertical-audit follow-up (Wave 1). No wire/schema change.

🤖 Generated with Claude Code

… agent

handle_gate_challenge() read a flat {gate_type, amount, currency} body and
split credential/agreement onto 403 by an `error` string. The canonical 402
(gate.402-response.json) and 403 (gate.403-response.json) instead carry
{error, resource, current_tier, required_tier, unmet_requirements[]}, where
every gate type arrives as an unmet requirement with a machine-readable
resolution_hint. The example — the one place an agent-builder copies from —
therefore never matched a real publisher's response.

Rewrite the parser to iterate unmet_requirements and build one proof per
entry, routed on each requirement's type (payment/credential/agreement/
identity/trust/connection), using the canonical proof shapes from
@eep-dev/gates. Add test_agent.py covering payment, multi-requirement,
403 access_forbidden, non-gate errors, and unsatisfiable custom types.

Also make the README and requirements honest: the example inlines the wire
contracts for readability and points to eep-gates/signer/validator for
production, rather than claiming to import packages it never used.

Signed-off-by: Ugur Cekmez <ucekmez@gmail.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant