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"}. The core uses this during heartbeat processing to verify your SDK is still responsive.
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 every 30 seconds to signal liveness. Without it, the core has no way to know whether your SDK process is still running.RegisterAgent and Heartbeat are the minimum 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.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.