In most real-world systems, “AI agents” sit on top of a polyglot stack:
- Python for data and ML
- TypeScript/Node for backend and APIs
- Rust/Go for performance-sensitive pieces
If your capability model only really exists in one language, you end up with:
- Duplicate logic in other languages
- Inconsistent validation and error handling
- Governance rules that only apply to the Python part
A more sustainable pattern is to treat the capability protocol as the primary artifact and the language SDKs as implementations.
Concretely:
- Specify a wire-level protocol and schema format.
- Define how metadata (risk, cost, ownership) and governance hooks (ACL, approvals, audit) attach to a capability.
- Build SDKs in your target languages that:
- Use the same conformance tests
- Expose idiomatic APIs
- Produce identical runtime behavior
Now a capability implemented in Rust can be:
- Called by a Python-based agent
- Exposed as an HTTP endpoint by a TypeScript service
- Invoked via CLI by ops teams
…without reinventing validation, approvals, or tracing.
If you are designing your own internal runtime, consider starting with the protocol and tests first, and only then layering language-specific ergonomics on top. It is slower upfront but pays off when your stack inevitably becomes polyglot.
Top comments (1)
Protocol-first with conformance tests as the real artifact is the pattern that survives polyglot teams, and CDP is the proof by counterexample: one wire spec, SDKs in every language, constant drift because there's no official conformance suite - every client effectively pins the browser version it was written against.
The hard part is governance metadata. Risk and cost fields look language-neutral on the whiteboard, then each SDK surfaces them idiomatically (Pydantic defaults vs Rust's Option vs TS optional properties) and 'identical runtime behavior' quietly dies in the serialization edges. Do you freeze JSON-level semantics in the conformance tests?