Documentation Index
Fetch the complete documentation index at: https://docs.getbindu.com/llms.txt
Use this file to discover all available pages before exploring further.
General Concepts
What is Bindu?
What is Bindu?
What is the A2A Protocol and why does Bindu use it?
What is the A2A Protocol and why does Bindu use it?
When should I use a Workflow vs. a Team (multi-agent team)?
When should I use a Workflow vs. a Team (multi-agent team)?
Do I need a DID if I'm running with AUTH__ENABLED=false?
Do I need a DID if I'm running with AUTH__ENABLED=false?
client_id becomes a DID (the Bindu default), and the agent demands a matching X-DID header + signature on every call. The cleanest path is to generate a DID once when you bindufy() your agent — bindufy writes it to .bindu/oauth_credentials.json and the same DID survives across restarts.I lost the seed file for my DID. Can I recover it?
I lost the seed file for my DID. Can I recover it?
metadata.public_key). Anything that referenced the lost DID (allowlists, peer agent configs) needs to be updated to point at the new one. Treat the seed file with .ssh/id_rsa-level care: chmod 600, never commit, back up to a password manager or HSM.Can I rotate my DID's keypair without changing the DID string itself?
Can I rotate my DID's keypair without changing the DID string itself?
sha256(public_key)[0..32] formatted as a UUID — change the keypair and the derived DID changes too. This is intentional: the DID is a fingerprint of the public key, so “rotating keys but keeping the DID” would defeat the verification chain. If you need to rotate, mint a new DID, register the new public key in Hydra, and update consumers.Getting Started Confusion
What's the difference between Bindu, the inbox, and the gateway?
What's the difference between Bindu, the inbox, and the gateway?
- Bindu — the agent framework itself. You wrap your handler with
bindufy()and get a Starlette HTTP server speaking A2A on port 3773 by default. - Gateway — a separate service (
gateway/) that plans and fans out work across multiple Bindu agents. You callPOST /planwith a high-level intent; the gateway decides which agents to invoke and orchestrates the multi-agent flow. - Inbox — the UI (
inbox/) that bootstraps a personal agent, registers it with Hydra, signs outbound messages, and renders agents as Gmail-shaped addresses (fleet+agent@getbindu.com). It’s the easiest way to talk to a fleet without writing a caller.
I called bindufy() and my script just hangs. Is that right?
I called bindufy() and my script just hangs. Is that right?
bindufy() starts a uvicorn server and blocks. That’s the intended behavior for a single-agent process. If you want to do other work after starting the server, run it in a background thread, use asyncio.create_task on the underlying coroutine, or run multiple agents as separate processes orchestrated by a process manager like supervisord or concurrently.Can I run multiple Bindu agents in one Python process?
Can I run multiple Bindu agents in one Python process?
examples/gateway_test_fleet/ pattern works. If you really need in-process composition, build one Bindu agent whose handler orchestrates several underlying framework agents (Agno team, LangGraph nodes, CrewAI crew).Where does my agent listen by default? How do I change it?
Where does my agent listen by default? How do I change it?
http://localhost:3773 (default_host=localhost, default_port=3773 in settings.py). Override with BINDU_PORT=4000 python agent.py or BINDU_HOST=0.0.0.0 BINDU_PORT=4000 python agent.py. If you need a different public URL than the bind address (e.g., behind a reverse proxy), set BINDU_DEPLOYMENT_URL=https://my-agent.example.com — that’s what the agent card advertises.My agent card shows url: 'http://localhost' even though I'm running on a real domain. Why?
My agent card shows url: 'http://localhost' even though I'm running on a real domain. Why?
BinduApplication defaults url to "http://localhost" and bindufy() only overrides it when you pass deployment.url through the manifest. Set BINDU_DEPLOYMENT_URL in your env, or pass an explicit url=... into the deployment dict you give to bindufy(). Peers fetching /.well-known/agent.json will then see the real address.How do I expose my local agent so another agent on a different machine can reach it?
How do I expose my local agent so another agent on a different machine can reach it?
- Development / demo:
bindufy(launch=True, ...)creates an FRP tunnel and publishes a public URL. Convenient, not durable. - Production: put the agent behind your own load balancer + TLS terminator and set
BINDU_DEPLOYMENT_URLto the public address. - Peer-to-peer over public internet: turn on mTLS so the agent serves HTTPS directly with a step-ca cert. See the mTLS section below.
Does Bindu need internet access to start?
Does Bindu need internet access to start?
https://hydra.getbindu.com). With AUTH__ENABLED=false, STORAGE_TYPE=memory, SCHEDULER_TYPE=memory, and a local LLM (Ollama, LM Studio), the agent runs fully offline. Hydra is the only mandatory external dependency when auth is on — and you can self-host Hydra in an air-gapped network.Installation & Setup
What Python version does Bindu require?
What Python version does Bindu require?
How do I install Bindu and its dependencies?
How do I install Bindu and its dependencies?
uv package manager. You can install the core framework by running uv add bindu.How do I set up Bindu inside a virtual environment?
How do I set up Bindu inside a virtual environment?
uv venv --python 3.12.9. Then activate it using source .venv/bin/activate (macOS/Linux) or .venv\Scripts\activate (Windows) before installing dependencies.Does Bindu work with Conda environments?
Does Bindu work with Conda environments?
conda create -n bindu-env python=3.12), activate it, and then run pip install uv to manage your Bindu dependencies.How do I upgrade Bindu without breaking existing agents?
How do I upgrade Bindu without breaking existing agents?
uv add bindu --upgrade. Bindu follows semantic versioning, meaning minor and patch updates are backward-compatible.Can I use Bindu without an internet connection (air-gapped)?
Can I use Bindu without an internet connection (air-gapped)?
InMemoryStorage and local LLMs (like Ollama). However, initial setup (downloading the LLM weights and installing Python packages) requires an internet connection.Environment Variables
Can I use a .env file instead of shell variables?
Can I use a .env file instead of shell variables?
.env file in your project root.Which environment variables does Bindu require?
Which environment variables does Bindu require?
OPENROUTER_API_KEY, OPENAI_API_KEY, or MINIMAX_API_KEY).How do I set environment variables on macOS / Linux?
How do I set environment variables on macOS / Linux?
export command in your terminal (e.g., export BINDU_PORT=4000), or add them to your ~/.bashrc or ~/.zshrc file.How do I set environment variables on Windows?
How do I set environment variables on Windows?
$env: prefix (e.g., $env:BINDU_PORT="4000").How do I manage variables across staging and production?
How do I manage variables across staging and production?
.env.staging and .env.production) and load the specific file in your deployment environment, or inject the variables directly via your CI/CD pipeline.Can I inject environment variables inside a Docker container?
Can I inject environment variables inside a Docker container?
ENV instruction in your Dockerfile, pass them via docker run -e, or use the environment mapping in a docker-compose.yml file.How do I rotate API keys without restarting my agent?
How do I rotate API keys without restarting my agent?
Switching Models
How do I switch between different LLM providers?
How do I switch between different LLM providers?
OpenAIChat → Anthropic; LangChain: swap ChatOpenAI → ChatAnthropic; CrewAI: swap the llm= argument) and update the API keys in your .env. The Bindu wrapper around your handler stays unchanged.How do I use a local model like Ollama or LM Studio with Bindu?
How do I use a local model like Ollama or LM Studio with Bindu?
http://localhost:11434 for Ollama, http://localhost:1234/v1 for LM Studio) and pass that agent to bindufy(). Bindu sees a normal handler — it doesn’t care that the LLM happens to be local.Can I use different models for different agents inside the same workflow?
Can I use different models for different agents inside the same workflow?
bindufy(). Bindu treats the whole composition as one agent with one DID; the model choices live entirely inside your handler.How do I fall back to a cheaper model when my primary model fails?
How do I fall back to a cheaper model when my primary model fails?
try/except fallback loop or use a framework like Tenacity inside your handler function to catch API errors and retry the prompt with a secondary model instance.Agent Communication
How do I connect a Bindu agent to an external A2A-compatible agent?
How do I connect a Bindu agent to an external A2A-compatible agent?
httpx or requests) to send a formatted POST request to the external agent’s URL from inside your handler.How does Bindu handle agent discovery across a distributed system?
How does Bindu handle agent discovery across a distributed system?
.well-known/agent.json endpoint, allowing for cryptographically verifiable discovery.Can Bindu agents communicate with LangChain or LangGraph agents?
Can Bindu agents communicate with LangChain or LangGraph agents?
handler function that you pass to bindufy().How do I pass context and memory between agents in a workflow?
How do I pass context and memory between agents in a workflow?
context_id provided in the incoming A2A message payload. Passing this ID to subsequent agents ensures they all read and write to the same conversational memory thread.What happens if an agent in the workflow fails mid-task?
What happens if an agent in the workflow fails mid-task?
failed and becomes immutable — refinements create a new task instead of reopening the old one. Bindu’s internal scheduler and storage layers have retry-with-backoff for transient infrastructure failures (Redis hiccups, Postgres locks), but your handler is not wrapped in automatic retries. If you want LLM-call retries, wrap them yourself with a library like tenacity inside your handler. See the Retry overview for what the framework retries on your behalf.Tasks & A2A Protocol Mechanics
What's the difference between taskId, contextId, and messageId?
What's the difference between taskId, contextId, and messageId?
messageId— one inbound or outbound message. Cheap, single-use.taskId— one unit of work the agent is tracking. Has a lifecycle (submitted→working→input-requiredorcompleted). The task is the thing you poll, cancel, and reference.contextId— a conversation thread that may contain many tasks. Use the samecontextIdacross calls when you want the agent to see prior turns.
Why can't I send a follow-up message to a completed task?
Why can't I send a follow-up message to a completed task?
completed, failed, canceled, rejected), it cannot be reopened. To continue the conversation, create a new task in the same contextId. If the new task should build on prior outputs, include the old task’s ID in referenceTaskIds. That’s the explicit dependency edge an orchestrator uses to chain work.How do I resume a task that's in input-required?
How do I resume a task that's in input-required?
message/send call with the same taskId (still in input-required, not terminal yet) and the user’s answer in the message body. The agent’s handler will be called again with the new message appended to the task history. Once your handler returns a non-input-required result, the task transitions to its terminal state.What is referenceTaskIds for?
What is referenceTaskIds for?
referenceTaskIds: [task2_id, task3_id] in the message. The agent (and any orchestrator like Sapthami) can then read the referenced tasks’ artifacts when planning Task4’s work. Without referenceTaskIds, dependencies live only in your application logic and orchestrators can’t reason about them.I'm getting 'params.configuration field required' — what's that?
I'm getting 'params.configuration field required' — what's that?
message/send request must include params.configuration.acceptedOutputModes, even if it’s just ["application/json"]. The JSON-RPC schema validator rejects the request before auth or the handler even runs. Minimum valid params:Can my agent return files instead of plain text?
Can my agent return files instead of plain text?
FilePart with two flavors: FileWithBytes (inline base64 payload) for small files, FileWithUri (presigned URL) for large ones. Your handler returns a part with kind: "file", and the artifact attached to the completed task carries the file part. Clients fetch it via tasks/get after the task reaches completed.Does Bindu support streaming responses?
Does Bindu support streaming responses?
message/stream instead of message/send — the agent returns a Server-Sent Events (SSE) stream of intermediate status updates and the final result. Use this when your handler produces incremental output (token-by-token LLM responses, multi-step tool calls) and you want clients to render progress instead of waiting for the whole task.How do clients get notified when a task completes without polling?
How do clients get notified when a task completes without polling?
tasks/pushNotificationConfig/set with a webhook URL on a task, and Bindu will POST a notification to that URL on every status transition. Webhook payloads are DID-signed by the agent so the receiver can verify origin. See the Notifications page for the webhook contract.How long are completed tasks kept around?
How long are completed tasks kept around?
STORAGE_TYPE=memory, tasks live for the lifetime of the process. With STORAGE_TYPE=postgres, tasks persist forever unless you implement a retention policy yourself — Bindu does not auto-purge completed tasks. For production, set up a periodic job to archive or delete tasks older than your retention window (e.g., 30 or 90 days).Multi-Agent Topologies
Can one Bindu agent call another from inside its handler?
Can one Bindu agent call another from inside its handler?
httpx, requests) to POST a JSON-RPC message/send to the other agent’s URL. If the called agent has auth on, you need a bearer token + DID signature on the outbound call — easiest to use the gateway as a signing proxy, or use the helper in bindu/utils/did/signature.py to build the signed headers. Pass contextId through if you want the called agent to see your task’s conversation history.How does agent discovery work in a fleet?
How does agent discovery work in a fleet?
/.well-known/agent.json. To discover an agent, fetch that URL — you get the agent’s DID, advertised skills, supported protocols, and capabilities. There is no central registry: a fleet “exists” because each agent’s URL is known to its callers (registered in the inbox, configured in the gateway, hardcoded by your orchestrator). For more sophisticated discovery, the negotiation extension (/agent/negotiation) lets agents bid on capability requests.When should I use the gateway vs. handler-to-handler calls?
When should I use the gateway vs. handler-to-handler calls?
How do I do a fan-out / fan-in across multiple agents?
How do I do a fan-out / fan-in across multiple agents?
- Gateway-driven: POST a single
/planrequest to the gateway with the high-level intent. The gateway parses, dispatches to several agents in parallel, and aggregates the results. - Handler-driven: in your orchestrator agent’s handler, use
asyncio.gatherto call N peer agents concurrently, then synthesize the responses. Each peer call produces its owntaskId; you can include all of them inreferenceTaskIdson the synthesis task so the dependency graph is explicit.
Can different agents share the same Postgres database?
Can different agents share the same Postgres database?
Does Bindu support gRPC?
Does Bindu support gRPC?
bindu/grpc/ for language-agnostic agent clients. The gRPC port is separate from the HTTP port (3773 by default for HTTP). Use gRPC when you need an agent driver in a non-Python language and don’t want to hand-roll the A2A JSON-RPC contract. See the Multi-Language Sidecar docs.Memory & State
What types of memory does Bindu support?
What types of memory does Bindu support?
InMemoryStorage for testing and PostgresStorage for production.How do I persist agent memory across sessions?
How do I persist agent memory across sessions?
STORAGE_TYPE=postgres and provide a DATABASE_URL in your environment variables. Bindu will automatically persist task histories and contexts.How do I give an agent access to a knowledge base or implement RAG?
How do I give an agent access to a knowledge base or implement RAG?
PDFKnowledgeBase or LangChain’s vector store retrievers inside your handler logic.How do I prevent the context window from overflowing on long tasks?
How do I prevent the context window from overflowing on long tasks?
Tools & Integrations
How do I give an agent access to custom tools or APIs?
How do I give an agent access to custom tools or APIs?
Can Bindu agents use skills and toolkits directly?
Can Bindu agents use skills and toolkits directly?
skill.yaml or a SKILL.md file describing the capability (id, name, description, input/output schema). You pass the directory path to load_skills([...]), and the agent advertises each loaded skill at /agent/skills/{skill_id}. There is no implicit skills/ folder the framework auto-scans — paths are registered explicitly via bindufy().How do I connect a Bindu agent to a SQL or vector database?
How do I connect a Bindu agent to a SQL or vector database?
SQLDatabaseToolkit or Agno’s PgVector).How do I build a human-in-the-loop step inside a workflow?
How do I build a human-in-the-loop step inside a workflow?
"state": "input-required" and a "prompt" asking for clarification. Bindu will pause the task until the user responds.Does Bindu support web browsing or web scraping?
Does Bindu support web browsing or web scraping?
DuckDuckGoTools or ScrapeGraph to your agent logic.Structured Outputs
How do I get my agent to return structured JSON instead of plain text?
How do I get my agent to return structured JSON instead of plain text?
response_model passing) and ensure your client sends acceptedOutputModes: ["application/json"] in the A2A request configuration.Not all models support native structured outputs. What happens then?
Not all models support native structured outputs. What happens then?
How do I validate and retry if the agent returns an invalid schema?
How do I validate and retry if the agent returns an invalid schema?
Tenacity inside your handler to catch JSON parsing errors or Pydantic ValidationErrors, and feed the error back to the LLM as a retry prompt.Rate Limiting & Cost Management
I'm hitting token-per-minute (TPM) limits. How do I fix this?
I'm hitting token-per-minute (TPM) limits. How do I fix this?
How do I run multiple agents in parallel without hitting limits?
How do I run multiple agents in parallel without hitting limits?
SCHEDULER_TYPE=redis. This allows you to queue tasks and control worker concurrency across distributed instances.How do I implement request caching or token budgeting?
How do I implement request caching or token budgeting?
Debugging & Common Errors
How do I enable debug logging to trace what my agents are doing?
How do I enable debug logging to trace what my agents are doing?
LOGGING__DEFAULT_LEVEL=DEBUG before starting your agent.I'm getting HTTP 401 with JSON-RPC error -32009. What does this mean?
I'm getting HTTP 401 with JSON-RPC error -32009. What does this mean?
AuthenticationRequiredError (code -32009), and it means the bearer token is missing, expired, or not recognized by the Hydra introspection endpoint the agent is pointing at. Note: Bindu uses opaque Hydra tokens introspected at runtime, not JWTs — the legacy error message mentions “JWT” but the actual flow goes through /admin/oauth2/introspect.Quick fixes in order: (1) mint a fresh token, (2) confirm your agent’s HYDRA__ADMIN_URL matches the Hydra that issued the token, (3) for local development, set AUTH__ENABLED=false to bypass auth entirely. See Making Authenticated Requests for the 4-gate decoder table.I'm getting HTTP 403 with details.reason: did_mismatch / public_key_unavailable / invalid_signature. What's the difference?
I'm getting HTTP 403 with details.reason: did_mismatch / public_key_unavailable / invalid_signature. What's the difference?
How do I check if authentication is actually enforced on my running agent?
How do I check if authentication is actually enforced on my running agent?
curl http://localhost:3773/health — if this returns 200 without an Authorization header, the agent is up but health is intentionally public. To check enforcement, POST a JSON-RPC method without a token: curl -X POST http://localhost:3773/ -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","id":"1","method":"message/send","params":{"message":{"role":"user","parts":[{"kind":"text","text":"hi"}],"messageId":"x","contextId":"y","taskId":"z"},"configuration":{"acceptedOutputModes":["application/json"]}}}'. If you get -32009, auth is on. If you get a normal task response, AUTH__ENABLED is false.My agent gets stuck in a tool-calling loop. How do I prevent this?
My agent gets stuck in a tool-calling loop. How do I prevent this?
max_tool_iterations=5).Why is my agent hallucinating tool names that don't exist?
Why is my agent hallucinating tool names that don't exist?
How do I test my agents without making real LLM API calls?
How do I test my agents without making real LLM API calls?
unittest.mock.patch to mock the LLM provider’s response, or build a simple mock handler that returns hardcoded text if a TEST_MODE environment variable is true.How do I trace agent runs with OpenTelemetry?
How do I trace agent runs with OpenTelemetry?
TELEMETRY_ENABLED=true and configure OLTP_ENDPOINT, OLTP_SERVICE_NAME, and OLTP_HEADERS in your environment. Bindu will automatically export traces to platforms like Langfuse, Arize, or any OTLP-compatible collector.OLTP_* (not OTLP_*) in the current code. Yes, that’s a typo of the OpenTelemetry Protocol acronym — it’s load-bearing in bindu/utils/config/enricher.py, so use OLTP_* when configuring your .env.Deployment
What's the recommended way to deploy a Bindu agent to production?
What's the recommended way to deploy a Bindu agent to production?
STORAGE_TYPE=postgres with a DATABASE_URL and SCHEDULER_TYPE=redis with a REDIS_URL, and call bindufy() with launch=False (the default) so no public FRP tunnel is created. Front the container with your own load balancer + TLS, and turn auth on with AUTH__ENABLED=true pointing at a production Hydra. For wire-level encryption between agents, see the Security Stack page for the full mTLS env block.How do I scale a multi-agent crew horizontally?
How do I scale a multi-agent crew horizontally?
REDIS_URL) and PostgreSQL database (DATABASE_URL) so they can share the task queue and memory state.What metrics does Bindu expose at /metrics?
What metrics does Bindu expose at /metrics?
submitted, working, input-required), worker utilization, queue depth, and storage operation durations. Scrape interval 15s is a reasonable default. Combine with the OTLP traces (TELEMETRY_ENABLED=true) for full request-path observability.How do I do a zero-downtime deploy?
How do I do a zero-downtime deploy?
DATABASE_URL and REDIS_URL. Roll one replica at a time: drain in-flight HTTP requests via a SIGTERM-triggered graceful shutdown (uvicorn handles this), let the second replica pick up new tasks from the shared Redis queue, then bring the new version up. Because tasks live in Postgres and the queue lives in Redis, the rolling restart doesn’t drop work in flight.What's a healthy /health response look like?
What's a healthy /health response look like?
GET /health returns 200 with a JSON body including application.penguin_id, application.agent_did, runtime version, and storage/scheduler readiness. The /healthz endpoint is a stricter k8s-style readiness probe — returns 200 only when storage and scheduler are both reachable. Use /health for liveness, /healthz for readiness gates.Can I run Bindu on Kubernetes?
Can I run Bindu on Kubernetes?
Deployment with N replicas, a Service for in-cluster traffic, an Ingress for external traffic, plus a ConfigMap for non-secret env (STORAGE_TYPE=postgres, SCHEDULER_TYPE=redis) and a Secret for credentials (DATABASE_URL, REDIS_URL, Hydra client secrets). Use /healthz as the readiness probe and /health as the liveness probe. For mTLS, store cert files in a Secret mounted at ~/.bindu/ or let the agent fetch them from step-ca on boot.mTLS & Wire Security
When do I need mTLS on top of Hydra OAuth2 + DID signatures?
When do I need mTLS on top of Hydra OAuth2 + DID signatures?
What's the minimum env block to turn mTLS on for an agent?
What's the minimum env block to turn mTLS on for an agent?
I set MTLS__ENABLED=true but the agent is still serving plain HTTP. Why?
I set MTLS__ENABLED=true but the agent is still serving plain HTTP. Why?
load_dotenv ordering. Bindu’s app_settings is constructed at module-import time. If your agent.py imports bindu before calling load_dotenv(), your MTLS__* env vars land in os.environ but never reach the settings singleton, and the agent silently falls back to HTTP.Fix: call load_dotenv() first, before any bindu import. Confirm by greping the boot log for Bootstrapping mTLS — if it’s missing, the settings never saw your env block.step-ca is rejecting my token with 'Requested audience step-ca has not been whitelisted'. What gives?
step-ca is rejecting my token with 'Requested audience step-ca has not been whitelisted'. What gives?
audience array doesn’t include step-ca. Recent Bindu builds reconcile this drift on every boot — restart the agent and the registration flow patches the audience. If you’re on an older build, delete .bindu/oauth_credentials.json and restart to force a fresh registration.How do I verify the cert my agent is actually serving?
How do I verify the cert my agent is actually serving?
https://hydra.getbindu.com#did:bindu:.... Issuer should be CN=Bindu Intermediate CA. Cert validity should be 24h from the renewal timestamp.How do I force-rotate an mTLS cert without waiting for the 24h TTL?
How do I force-rotate an mTLS cert without waiting for the 24h TTL?