Add Bindu A2A integration example (DID-identified agent + optional x402 micropayments)#2
Open
raahulrahl wants to merge 2 commits into
Open
Add Bindu A2A integration example (DID-identified agent + optional x402 micropayments)#2raahulrahl wants to merge 2 commits into
raahulrahl wants to merge 2 commits into
Conversation
Run ContractGuard as a discoverable, DID-identified A2A microservice without touching core analyzer code. Peers send a `text` or base64 `file` part (PDF/DOCX/TXT/MD/RTF) and get back the existing AnalysisResult JSON. Optional pay-per-scan via x402 (USDC on Base) — uncomment one block in agent.py. - examples/bindu/agent.py: handler wrapping analyze_contract() - examples/bindu/README.md: what/why, setup, curl examples, response shape - examples/bindu/.env.example: minimal config (OPENROUTER_API_KEY) - README.md: new Integrations section linking the example Purely additive: no changes to contractguard/, no new required deps, CLI and Gradio UI unaffected.
…resp
End-to-end testing against bindu 2026.21.1 revealed three issues in the
first version:
1. Handler walked `parts[]`, but Bindu's manifest worker normalises A2A
messages to OpenAI-style `{role, content}` before invoking the handler
(text parts joined with " "). Result: the handler never received any
contract text and always returned `no_contract`. Rewritten to read
`m["content"]` directly — drops ~80 lines of dead code.
2. README's curl examples used `"id": "1"` for the JSON-RPC envelope.
Bindu's pydantic validator rejects non-UUID ids with a 400. Switched
all examples to proper zero-UUIDs.
3. File-upload path didn't actually work. Bindu's `FileInterceptor` reads
flat `{kind, mimeType, data}` while the A2A `FilePart` schema (and the
JSON-RPC validator) expect nested `{kind, file: {bytes, mimeType}}` —
round-trip is broken in this version. Cut the file section; users
pre-extract with `contractguard.parser.extract_text()` and send text
instead.
Also added a complete try-it-out section:
- One-shot bash script that sends `examples/sample_lease.txt`, polls
`tasks/get`, and prints the DID signature + parsed analysis JSON.
- Sample request body (annotated A2A envelope).
- Sample response — real `tasks/get` output captured by running this
agent against the sample lease (lease type, F grade, 15/100, with
trimmed red_flags / warnings / good_clauses / missing_protections).
Verified end-to-end: server starts, agent card resolves with the right
DID, `message/send` is accepted, handler runs, real OpenRouter call
succeeds, result artifact carries a valid Ed25519 signature.
Author
|
End-to-end tested against
Also added a complete try-it-out section with a copy-paste bash script, a sample request body, and a sample response — the response was captured by running this agent against Verified working end-to-end:
Apologies for shipping the first revision without doing this loop. Happy to keep iterating. |
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary
Adds
examples/bindu/showing how to run ContractGuard as a discoverable, DID-identified A2A agent using Bindu. Peers callmessage/sendwith either atextpart (paste the contract) or a base64filepart (PDF / DOCX / TXT / MD / RTF) and receive the existingAnalysisResultJSON — no schema changes.The integration is purely additive: nothing under
contractguard/is modified,binduis not a required dependency, and the CLI / Python API / Gradio UI all keep working unchanged.This addresses one bullet from the existing Contributing list ("Build integrations — MCP server, VS Code extension, Slack bot, etc."): A2A is the protocol for agent-to-agent calls, so wrapping ContractGuard with
bindufy()turns it into a building block that any A2A orchestrator can chain into longer workflows.What you get when ContractGuard is bindufied
/.well-known/agent.json— agent marketplaces and orchestrators can find ContractGuard and know what it does.did:bindu:…) — each analysis is attributable to a cryptographically-verifiable agent. Result artifacts are signed with the agent's Ed25519 key, so a review can be presented as tamper-evidence ("ContractGuarddid:bindu:…said this at timestamp T").message/send.agent.pyto charge USDC on Base per analysis. Short path from "open-source CLI" to "monetised hosted service" without a SaaS layer.Files
examples/bindu/agent.py— handler wrappinganalyze_contract(); handles text parts (with the first short text part treated as a prompt and echoed back) and base64 file parts via the existingcontractguard.parser.extract_textpath.examples/bindu/README.md— setup, run, curl examples for both inline text and PDF upload, response shape, x402 instructions, limits.examples/bindu/.env.example— minimal config (OPENROUTER_API_KEY), with optional model / language / author overrides.README.md— new "Integrations" section linking to the example.Test plan
python -c "import ast; ast.parse(open('examples/bindu/agent.py').read())"— passesbinduinstalled{"error": "no_contract", ...}JSON for an empty input_collect_inputs()correctly decodes a base64filepart usingexamples/sample_lease.txt(returns the full 4,015-char contract and the leading prompt)analyze_contract()which already has its own coveragebindufy(config, handler)server startup — recommended manual smoke from the README's instructionsNotes
anthropic/claude-sonnet-4,en); they can be overridden withCONTRACTGUARD_MODELandCONTRACTGUARD_LANG.MAX_CONTRACT_CHARStruncation behaviour fromanalyzer.pyis unchanged — long contracts are silently truncated as today.examples/bindu/.env.exampleonly documents env vars — no real secrets.Happy to iterate on style, placement, or naming if you'd prefer it under a different path (e.g.
integrations/bindu/).