Programmatic access to the agent comes in three shapes, and the third is built on a fundamentally different principle from the first two. The native TypeScript SDK gives you the agent right inside your own process; the Python SDK talks to the same bridge, only bundled into the package and started by it. The bridge is a small local server with the TypeScript SDK running inside it, exposing the same agent surface outward over a stable protocol on top of Connect and protobuf. It exists for the places where there is no native SDK: Go, Rust, Java, C#, any other language.
The naive line of thought goes like this: since there is no SDK for my language, I will write a client against the network interface directly, because everything speaks HTTP. The thought is natural and half correct. A separate network interface for cloud agents does exist, works over HTTP and requires nothing local. If the task is to launch an agent in the cloud and collect the result, that is the right choice, and the bridge is an extra link with nothing to justify it.
It breaks on the second requirement - when the agent is needed locally, with your tools and your state storage. The agent surface does not reduce to one call with a reply: it is creating a conversation, resuming an interrupted one, sending messages, reading the stream of events as work proceeds, reaching for the caller's own tools and reaching for a state store. Writing that again in your language means rewriting not a client but the agent loop itself, and repeating the exercise on every change made on the other side.
The bridge removes that question by keeping the loop inside the TypeScript SDK and exposing a contract outward. The contract is described by a protobuf package and split into services, and separating them helps not only by purpose but by the direction of the call. Below is that map: the agent service, the reference service and bridge control are called by the adapter; the tool and store callbacks are addressed by the bridge to the adapter itself; the shared layer of messages and errors belongs to both sides.
The reverse direction is the least obvious part of the design. The adapter in your language is not only a client - it is also a server: for the agent to call your tool or read your state, the bridge has to knock somewhere. Hence a practical requirement on the adapter's code: it holds two roles at once and lives as long as the conversation lives. A client written as a sequence of requests with waiting for replies will stall on the very first tool of your own.
| Service | What is in it | Direction of the call |
|---|---|---|
| The agent service | Create and resume agents, send prompts, stream runs, artifacts and usage | The adapter calls the bridge |
| The reference service | Identity, available models, repositories | The adapter calls the bridge |
| Bridge control | Ping, version, shutdown, tool-callback registration | The adapter calls the bridge |
| Tool callbacks | The caller's own tools | The bridge calls the adapter |
| Store callbacks | The caller's own state storage | The bridge calls the adapter |
| Shared messages and errors | Types and codes common to all services | A shared layer of the contract |
There are two secrets in this scheme, and they should not be confused. The first is the access key of a user or a service account; it is taken from the dashboard and handed to the bridge as an option or an environment variable, and the bridge presents itself with it outward when it reaches the network interface over HTTPS. The second is the bearer token that the bridge issues during the handshake; the adapter attaches it to every call. The server itself comes up on the loopback address, which is to say it listens to this machine and nobody else.
There is a reservation about transport that trips people up most often. The protocol looks like gRPC and is described with the same means, but classic gRPC over HTTP/2 will not connect to the bridge: the server speaks HTTP/1.1, and it has to be addressed either with a Connect client or with plain POST requests carrying protobuf or JSON. Versioning, on the other hand, is promised to be gentle: breaking changes arrive as a separate package alongside the existing one rather than rewriting it in place.
The price of the extra link is made of three things. The first is the process: it has to be downloaded for the right platform and architecture, started, waited on until ready, watched for liveness and shut down properly, and all of that falls on your code rather than on a library. The second is debugging: an intermediary now stands between your program and the agent, and every failure comes with the extra question of whose side it is. The third is support: adapters for languages without a native SDK are written by the community, and responsibility for their compatibility with new versions lies with whoever picked them up. Request pooling and pricing, meanwhile, follow the same rules as the editor and cloud agents; the bridge creates no separate economics.
The bridge is chosen by elimination, and rightly so. TypeScript and JavaScript - the native SDK. Python - its own SDK, with the bridge already packaged inside, so there is no need to raise it separately. Cloud agents over HTTP only, without local execution - the cloud network interface. Everything else, which is to say Go, Rust, Java, C#, - the bridge. The result is checked in two steps: first the control calls confirm that the process came up and answers with the expected version, then a real conversation is run with one tool of your own. The second step is mandatory: it is the only one that proves the reverse direction of calls works and not just the forward one.
The typical failures are predictable. Taking the bridge where the cloud network interface would have sufficed, and getting a process to maintain instead of a single request. Raising the bridge by hand next to the Python SDK, where it already sits inside. Poking at it with a classic gRPC client and spending a long time reading connection errors. Writing the adapter as a client only and finding out on the first tool of your own. Forgetting to shut the process down and leaving it hanging after the program ends. And treating an adapter written by the community as part of the product, and its compatibility as somebody else's concern.