by GetBindu
Bindu: The identity, communication, and payments layer for AI agents.
# Add to your Claude Code skills
git clone https://github.com/GetBindu/BinduLast scanned: 4/20/2026
{
"issues": [],
"status": "PASSED",
"scannedAt": "2026-04-20T06:15:01.477Z",
"semgrepRan": false,
"npmAuditRan": true,
"pipAuditRan": true
}No comments yet. Be the first to share your thoughts!
Here's the situation. You built an agent. It works. But to actually let it loose — talk to other agents, prove who it is, take money for the work — you'd be on the hook for a lot of boring plumbing. A DID library to integrate. An OAuth flow to set up. Payment middleware. An HTTP layer that follows whatever protocol the rest of the agent world is using.
Bindu is all of that plumbing, behind one function call. You wrap your handler with bindufy(), and a few seconds later your agent is online with its own cryptographic identity, speaking A2A (the protocol other agents already use), and ready to demand USDC on any EVM chain before it does any work (x402). Your handler stays as small as (messages) -> response. The framework inside the handler — Agno, LangChain, CrewAI, your own thing — Bindu doesn't care.
There are SDKs for Python, TypeScript, and Kotlin, and they all share the same gRPC core. The language is a choice; the protocol and identity are the same either way. When you're ready to go deeper, the docs are the next stop.
You'll need Python 3.12+ and uv.
uv add bindu
If you're hacking on Bindu itself rather than using it:
git clone https://github.com/getbindu/Bindu.git
cd Bindu
uv sync --dev
To run the examples you'll need an API key for at least one LLM provider — OPENROUTER_API_KEY, OPENAI_API_KEY, or MINIMAX_API_KEY.
Build the agent you want, hand it to bindufy(), and it's online. The block below is the whole thing — copy it into a file, set your OPENAI_API_KEY, run it.
import os
from bindu.penguin.bindufy import bindufy
from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno.tools.duckduckgo import DuckDuckGoTools
agent = Agent(
instructions="You are a research assistant.",
model=OpenAIChat(id="gpt-4o"),
tools=[DuckDuckGoTools()],
)
config = {
"author": "you@example.com",
"name": "research_agent",
"description": "Research assistant with web search.",
"deployment": {"url": "http://localhost:3773", "expose": True},
"skills": ["skills/question-answering"],
}
def handler(messages: list[dict[str, str]]):
return agent.run(input=messages)
bindufy(config, handler)
The agent is now live at http://localhost:3773. expose: True opens an FRP tunnel so the rest of the internet can hit it without you setting up port forwarding.
import { bindufy } from "@bindu/sdk";
import OpenAI from "openai";
const openai = new OpenAI();
bindufy({
author: "you@example.com",
name: "research_agent",
description: "Research assistant.",
deployment: { url: "http://localhost:3773", expose: true },
skills: ["skills/question-answering"],
}, async (messages) => {
const response = await openai.chat.completions.create({
model: "gpt-4o",
messages: messages.map(m => ({ role: m.role as "user" | "assistant" | "system", content: m.content })),
});
return response.choices[0].message.content || "";
});
The TypeScript SDK spawns the Python core in the background — you won't see it, and you don't need any Python in your own codebase. Same protocol, same DID. Full example in examples/typescript-openai-agent/.
curl -X POST http://localhost:3773/ \
-H 'Content-Type: application/json' \
-d '{
"jsonrpc": "2.0",
"method": "message/send",
"id": "<uuid>",
"params": {
"message": {
"role": "user",
"kind": "message",
"parts": [{"kind": "text", "text": "Hello"}],
"messageId": "<uuid>",
"contextId": "<uuid>",
"taskId": "<uuid>"
}
}
}'
Then poll tasks/get with the same taskId until state hits completed.
Most agent frameworks treat security as your problem. Bindu treats it as transport.
When an A2A request lands on a Bindu agent, three different middlewares fire before your handler sees the body — and each one answers a question the other two cannot:
| Layer | The question it answers | What it actually is |
|---|---|---|
| mTLS | Is the socket itself encrypted and mutually authenticated? | X.509 cert from Smallstep step-ca, SAN = DID, 24-hour TTL, auto-renewed in-process |
| OAuth2 via Hydra | Is the caller allowed to perform this operation right now? | Ed-style bearer token, ~1-hour TTL, validated via Ory Hydra introspection |
| DID signature | Was this exact JSON body authored by the DID it claims? | Ed25519 signature over canonical body, carried in X-DID-Signature |
You don't pick one. You don't bolt them on. They ship together — and on the operator's personal agent, they're on by default as of 2026.21.1.
Why three layers, not one? Because each fails safe in a way the others can't:
The cert lives at the socket. The bearer token lives in the header. The signature lives in the body. Each one rejects a class of attack the others are blind to. No agent framework we surveyed ships all three out of the box.
→ The full story: docs/SECURITY_STACK.md walks through what each layer does, how a single request flows through all three, today's defaults, the five real bugs we hit shipping default-on mTLS, and a troubleshooting matrix.
Every row here links out to the guide that actually goes into it.
| Feature | What it does | Docs |
|---|---|---|
| A2A JSON-RPC | The protocol other agents already speak. message/send, tasks/get, message/stream on port 3773. | — |
| mTLS transport | The socket is encrypted and mutually authenticated. Each agent gets a real X.509 cert from step-ca (SAN = DID), serves uvicorn over TLS, and renews itself every ~16 hours. On by default for the inbox personal agent in 2026.21.1. | SECURITY_STACK.md · MTLS_DEPLOYMENT_GUIDE.md |
| DID identity | Every response your agent sends is signed with an Ed25519 key. Callers verify with a W3C DID — there's no shared secret to leak, no central authority to query, and the same DID is the cert's SAN, the OAuth2 client_id, and the message signer. All three have to agree, or the request is rejected. | DID.md |
| OAuth2 via Hydra | Scoped bearer tokens (agent:read, agent:write, agent:execute) instead of one key that opens every door. Each agent self-registers as a Hydra client at boot — its DID IS its client_id, so authorization, identity, and transport-layer cert all point at the same actor. | [AUTHENTICATION.md](docs/A