diff --git a/workspace/act/act/__init__.py b/workspace/act/act/__init__.py index db354f1..f2520a3 100644 --- a/workspace/act/act/__init__.py +++ b/workspace/act/act/__init__.py @@ -1,4 +1,4 @@ -"""Agent Compact Token (ACT) — Reference Implementation. +"""Agent Context Token (ACT) — Reference Implementation. A JWT-based format for autonomous AI agents that unifies authorization and execution accountability in a single token lifecycle. diff --git a/workspace/act/pyproject.toml b/workspace/act/pyproject.toml new file mode 100644 index 0000000..14412fc --- /dev/null +++ b/workspace/act/pyproject.toml @@ -0,0 +1,23 @@ +[build-system] +requires = ["setuptools>=68.0"] +build-backend = "setuptools.build_meta" + +[project] +name = "act" +version = "0.1.0" +description = "Agent Context Token (ACT) — JWT-based authorization and execution accountability for AI agents" +requires-python = ">=3.11" +dependencies = [ + "cryptography>=42.0", +] + +[project.optional-dependencies] +dev = [ + "pytest>=8.0", +] + +[tool.setuptools.packages.find] +where = ["."] + +[tool.pytest.ini_options] +testpaths = ["tests"] diff --git a/workspace/docs/poc-mcp-langgraph-plan.md b/workspace/docs/poc-mcp-langgraph-plan.md new file mode 100644 index 0000000..ed8e49e --- /dev/null +++ b/workspace/docs/poc-mcp-langgraph-plan.md @@ -0,0 +1,79 @@ +# PoC Plan — ACT + ECT over MCP with LangGraph + +**Target**: end-to-end working demo for IETF 123 preparation and draft credibility. +**Location**: `demo/act-ect-mcp/` (moved out of `workspace/poc/` to be a first-class peer of `paper/` and `workspace/`) +**Date**: 2026-04-12 + +## Scenario + +A user issues a **mandate** (ACT authorization token) to a LangGraph agent: "research topic X, produce summary." The agent, running in a LangGraph `StateGraph`, calls two tools exposed by an MCP server: + +1. `search(query)` — returns fake hits +2. `summarize(text)` — returns fake summary + +Every MCP tool call is authenticated by: +- **ACT mandate** in `Authorization: Bearer ` header (capability check: `cap=["mcp.search","mcp.summarize"]`) +- **ECT execution context** in a signed HTTP header per `draft-ietf-wimse-http-signature-03` using the `wimse-aud` signature parameter +- Tool-call body hashed into ECT `inp_hash` + +On tool success, the agent mints an **ACT execution record** with: +- `status="completed"` +- `pred=[mandate.jti]` for the first call, `pred=[mandate.jti, prev_exec.jti]` for subsequent calls (DAG, not linear) +- `inp_hash` / `out_hash` bound to request/response bodies + +A standalone `verify` CLI walks the resulting ACT ledger + ECT store and prints the DAG. + +## Components + +``` +poc/mcp-langgraph/ +├── README.md # how to run, what it proves +├── pyproject.toml # depends on ietf-act, ietf-ect, mcp, langgraph, fastapi +├── keys/ # generated ES256 keys (gitignored) +├── src/ +│ ├── keys.py # key gen + JWKS loader +│ ├── tokens.py # ACT mandate/exec minters, ECT header builder +│ ├── http_sig.py # minimal http-signature-03 signer/verifier +│ ├── server.py # MCP server (FastMCP streamable-http) + ECT/ACT middleware +│ ├── agent.py # LangGraph agent + MCP client, injects ACT+ECT +│ └── verify_cli.py # walks ledger, prints DAG +├── demo.sh # end-to-end: start server, run agent, run verifier +└── tests/ + ├── test_token_flow.py # one tool call → one exec record linked via pred + └── test_dag_shape.py # two tool calls → DAG with expected pred edges +``` + +## Build sequence (verifiable increments) + +1. **Skeleton + deps**: `pyproject.toml`, package layout, install works. +2. **Keys + tokens**: `keys.py`, `tokens.py`. Unit test: mint mandate, mint exec, verify both. +3. **HTTP signature**: `http_sig.py`. Unit test: sign request, verify (round-trip). +4. **MCP server**: FastMCP with two fake tools + ASGI middleware that verifies ACT+ECT on every call. Manual curl test. +5. **LangGraph agent**: StateGraph, `langchain-mcp-adapters` with custom headers callback. No LLM — scripted node sequence that calls both tools. +6. **Verifier CLI**: prints the DAG (mandate → exec1 → exec2). +7. **End-to-end `demo.sh`**: spawns server, runs agent, runs verifier. Green = PoC done. + +## Explicit non-goals + +- Real LLM via Ollama (local, zero API cost). `create_react_agent` decides which MCP tools to call. Token flow is deterministic regardless of LLM output. +- No registration / discovery of agents — assume pre-shared JWKS. +- No distributed SCITT anchoring — in-memory ledger only. +- No Go interop in this PoC (Python + Python). Go path tracked separately. + +## Tradeoffs + +**Real MCP vs. MCP-shaped**: use real MCP SDK (FastMCP server + `streamablehttp_client`). More credible for IETF reviewers; adds dep weight. If the MCP SDK blocks us from injecting ECT on the HTTP layer, fall back to FastAPI endpoints that mirror the MCP JSON-RPC shape. + +**LLM**: real. Ollama `qwen3:8b` as default (local, free, reproducible per CLAUDE.md cost policy). Swap to Anthropic/OpenAI via env var. LangGraph `create_react_agent` wires LLM + MCP tools. + +## Success criteria + +- `demo.sh` exits 0, verifier prints a DAG with 1 mandate + 2 execs + correct `pred` edges. +- All unit tests green. +- README shows a reviewer can reproduce in under 5 minutes (`uv sync && ./demo.sh`). + +## Questions before coding + +- OK to put PoC under `workspace/poc/mcp-langgraph/` (new dir), not under `packages/`? +- OK to pin `mcp>=1.0`, `langgraph>=0.2`, `langchain-mcp-adapters` as deps? +- LangGraph without an LLM is fine for v1 of the PoC, right?