You have seen how the TypeScript SDK works. Now imagine doing the same thing in Rust, Go, Swift, or any language that has gRPC support. That is what this page is for. The key insight is that the goal is not to rewrite the core. The goal is to build a new driver that can plug into the same engine. Because the sidecar keeps infrastructure centralized, each new language only needs a thin adapter — usually 200–400 lines of actual logic.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.
The architectural rule is simple: new languages get new drivers, not new engines.
What an SDK Does
Before we dive into the steps, it helps to understand the four responsibilities every SDK shares. Under the hood, the SDK does four things:- Implements
AgentHandler— a gRPC server that receivesHandleMessagescalls from the core and invokes the developer’s handler - Calls
BinduService.RegisterAgent— a gRPC client that registers the agent with the core - Launches the Python core — spawns
bindu serve --grpcas a child process - Exposes
bindufy(config, handler)— the developer-facing API that orchestrates all of the above
proto/agent_handler.proto is the single source of truth. As long as your SDK speaks that contract, it works with the core.
Step 1: Generate gRPC Stubs
Before your SDK can talk to the core, it needs to speak the same language. The first job is to generate typed client and server stubs from the protobuf definition. Every gRPC ecosystem has its own tooling for this:| Language | Tool | Command |
|---|---|---|
| Rust | tonic-build | Add tonic-build to build.rs, it compiles the proto at build time |
| Go | protoc-gen-go-grpc | protoc --go_out=. --go-grpc_out=. proto/agent_handler.proto |
| Swift | grpc-swift | protoc --swift_out=. --grpc-swift_out=. proto/agent_handler.proto |
| C# | Grpc.Tools | NuGet package auto-generates from .proto in the project |
Step 2: Implement AgentHandler (Server)
This is the server that the core will call when work arrives. It is the language-specific half of the sidecar — how the engine talks back to the driver. Of the three RPCs,HandleMessages is the critical one.
HandleMessages / HandleMessagesStream
This RPC receives conversation history, calls the developer’s handler, and returns the response. Here is the shape of the request and response:HandleResponse are straightforward:
- If the handler returns a plain string, set
contentto the string and leavestateempty. - If the handler returns a state transition, set
stateto"input-required"or"auth-required"andpromptto the follow-up question. - If the handler throws, return a gRPC
INTERNALerror with the error message. - Unary path (
HandleMessages): Setis_finaltotrue(there is only one response). - Streaming path (
HandleMessagesStream): Yield multipleHandleResponsechunks withis_final: false, and setis_final: trueon the last chunk. - Both paths use the exact same
HandleResponsemessage shape.
GetCapabilities
Return static info about the SDK. This is how the core discovers what your agent supports.HealthCheck
Return{healthy: true, message: "OK"}. GrpcAgentClient.health_check() can call
this on demand, but the core’s BinduService.Heartbeat handler does not
invoke it — heartbeats only update the registry timestamp. Implement the RPC
anyway so future eviction sweeps and external watchdogs work.
Step 3: Implement BinduService Client
Now build the other direction — the client that talks from your SDK into the core. This is how your SDK registers the agent and keeps it alive.RegisterAgent
This is the main entry point. It sends config, skills, and the SDK’s callback address:config_json is a JSON string matching the Python bindufy() config format. That is intentional. The schema lives in one place, and SDKs serialize to it.
Heartbeat
Call this on a regular interval — the reference TypeScript SDK uses 30 seconds — to signal liveness. The cadence is an SDK convention, not a core-enforced contract; the Python core recordslast_heartbeat but does not currently evict stale
agents, so the value mainly matters when an external watchdog or future eviction
sweep is wired in.
UnregisterAgent
Call this when your SDK process is shutting down cleanly so the core can release the agent slot immediately. Today this is the only way an agent leaves the registry — the Python core does not currently evict on heartbeat timeout, so withoutUnregisterAgent a crashed SDK leaks its registry entry until the core
restarts.
The TypeScript reference SDK does not currently call
UnregisterAgent — its SIGINT
handler only clears the heartbeat interval and force-shuts the gRPC server. New SDKs
should improve on this and invoke UnregisterAgent from their shutdown path.RegisterAgent, Heartbeat, and UnregisterAgent are the control plane for the sidecar.
Step 4: Implement Core Launcher
The SDK must be able to start the engine automatically. This is what makes the developer experience feel local even though the architecture is split. Without it, the developer would need to manually start the Python core in a separate terminal — and that would break the illusion of a single-process experience.Pass the executable and arguments as a properly split array to your language’s process
spawner — not as a single shell string.
Pass the executable and arguments as a properly split array to your language’s process
spawner — not as a single shell string.
If not, check if uv is available
Run
uv with args ["run", "bindu", "serve", "--grpc", "--grpc-port", "3774"]If not, fall back to Python module
Run
python3 with args ["-m", "bindu.cli", "serve", "--grpc", "--grpc-port", "3774"]Step 5: Implement bindufy()
At this point, you have all the pieces. The last step is to wire them behind one developer-facing function. This is the moment where your SDK goes from “a collection of gRPC plumbing” to “a one-line developer experience.”
Skill Loading
Skills live in the developer’s project, not in the core. Your SDK is responsible for reading them and shipping their contents to the core during registration. This way the core does not need filesystem access to the SDK’s project directory.Extract metadata
For YAML: parse the body and pull out
name and description (the reference TypeScript SDK
extracts only these two fields client-side — the rest is left to the core to parse from raw_content).
For Markdown: send raw_content as-is with format: "markdown"; the reference TS SDK does not
parse YAML frontmatter out of SKILL.md. If your SDK wants to surface more metadata locally
(e.g. for logging), parse it yourself — the core treats raw_content as the source of truth.Send as SkillDefinition
{ name, description, tags, input_modes, output_modes, version, author, raw_content, format }.
tags, input_modes, and output_modes default to sensible values ([], ["text/plain"],
["text/plain"] in the TS SDK). Only raw_content and format are strictly required for
the core to fully reconstruct the skill.Testing Your SDK
The fastest way to keep an SDK honest is to test both the transport and the sidecar lifecycle. Start with unit tests to verify serialization, then work up to integration tests that exercise the full round trip.Unit test
Unit test
Mock the gRPC channel and verify
HandleMessages correctly invokes the handler and
serializes the response.Integration test
Integration test
Start a real Bindu core with
bindu serve --grpc, register an agent from your SDK,
send an A2A message, and verify the response. The Python E2E tests in
tests/integration/grpc/test_grpc_e2e.py show exactly this pattern.Smoke test
Smoke test
Run one of the examples end to end and
curl the agent.Reference: TypeScript SDK
If you want a concrete model to follow, the TypeScript SDK is the reference implementation. It is intentionally small — most of the complexity lives in the core, not in the SDK.| File | What it does | Lines |
|---|---|---|
src/index.ts | bindufy() function + skill loader | ~220 |
src/server.ts | AgentHandler gRPC server | ~130 |
src/client.ts | BinduService gRPC client | ~105 |
src/core-launcher.ts | Spawns Python core | ~170 |
src/types.ts | TypeScript interfaces | ~120 |
TypeScript SDK
See how the reference driver behaves from the developer’s point of view
API Reference
Review the protobuf messages and service contracts directly
Publishing
Once your SDK works, publish it to the language’s standard package registry so others can use it:| Language | Registry | Package name convention |
|---|---|---|
| Rust | crates.io | bindu-sdk |
| Go | Go modules | github.com/getbindu/bindu-sdk-go |
| Swift | Swift Package Manager | bindu-sdk |
| C# | NuGet | Bindu.Sdk |
Include the proto file in the package so users do not need to download it separately.