
Why the language you pick to orchestrate AI agents defines architectural constraints you’ll be living with for years — and why mature agent systems will be polyglot by necessity, not by choice.
There’s a recurring dismissal I hear whenever language choice comes up in the context of agentic systems: “The model does the heavy lifting. The orchestration layer is just glue code.”
This is wrong in a way that only becomes visible after you’ve committed to a stack, scaled past the prototype, and started hitting walls that no prompt engineering can fix.
I’ve been building agent infrastructure in both Go and Python over the past year — a context engineering platform in Go, a multi-LLM orchestration layer in Python — and the lesson is clear: the language you choose doesn’t just affect developer experience. It defines your concurrency model, your failure modes, your type safety boundaries, and ultimately the architectural ceiling of what your agent system can do.
The choice matters. Here’s why.
The illusion of “just glue code”
The “glue code” framing comes from a mental model where the agent system is simple: receive a prompt, call an LLM API, return a response. In that world, any language works. You’re just serializing JSON and making HTTP calls.
But real agent infrastructure isn’t that. It’s:
- Parallel tool execution — an agent that needs to call a database, a search API, and a code interpreter simultaneously, then synthesize the results before deciding its next step.
- Long-running sessions — multi-step workflows that maintain state across dozens of LLM calls, sometimes over minutes, sometimes over hours.
- Shared memory across agents — multiple agent instances that need to read and write to a common context without corrupting each other’s state.
- Graceful degradation — handling LLM timeouts, rate limits, partial responses, and tool failures without crashing the entire session.
This is systems engineering, not scripting. And systems engineering is where language choice has always mattered.
Python: the gravity well
Let’s start with the obvious. Python dominates the AI ecosystem. LangChain, LlamaIndex, CrewAI, AutoGen, the Anthropic SDK, the OpenAI SDK — the entire tooling layer assumes Python. If you want to prototype an agent in an afternoon, Python is the only rational choice.
But prototypes aren’t production, and here’s where the friction starts.
Concurrency is bolted on, not built in. Python’s asyncio works, but it's a layer on top of a language that was designed for sequential execution. The moment your agent needs true parallelism — say, running three tool calls simultaneously while monitoring a timeout — you're fighting the GIL or reaching for multiprocessing, which introduces serialization overhead and shared-state complexity that the language wasn't designed to handle elegantly.
Type safety is advisory. Python’s type hints are excellent for documentation and IDE support. They are not enforced at runtime. In an agent system, where you’re constantly deserializing LLM outputs into structured objects, this means your type errors surface in production, not at compile time. When the LLM returns an unexpected field type or a missing key, Python shrugs and continues — often silently — until something downstream breaks in a way that’s hard to trace.
Memory management is implicit. For short-lived scripts, this is fine. For a long-running agent orchestrator that accumulates context across dozens of steps, Python’s garbage collection behavior can introduce latency spikes that are hard to predict and harder to debug.
None of this makes Python a bad language. It makes it a language optimized for a different problem: rapid iteration, rich ecosystem access, and low barrier to entry. For the “last mile” of agent behavior — prompt engineering, tool definition, evaluation — Python is unbeatable. For the infrastructure underneath, it starts to show its seams.
Go: the quiet fit
Go is an unusual choice in the AI world, and that’s precisely what makes it interesting.
When I chose Go for the context engineering platform — the system responsible for managing shared state, decision graphs, and parallel agent sessions — the reasoning was architectural, not aesthetic.
Goroutines are the right primitive. An agent orchestrator’s core job is managing concurrent operations: multiple tool calls, parallel context reads, timeout supervision. Go’s goroutine model — lightweight, multiplexed onto OS threads, with channels for communication — maps almost directly onto this problem. You don’t bolt concurrency on; you think in concurrent terms from the start.
The type system catches the right things. Go’s type system isn’t fancy. No generics wizardry (well, not much), no algebraic types, no pattern matching. But it’s strict, it’s enforced at compile time, and it forces you to handle errors explicitly. In an agent system where every external call can fail — LLM APIs, tool executions, context reads — Go’s if err != nil pattern, much maligned as it is, creates a culture of explicit error handling that pays dividends in production.
Predictable performance. Go compiles to native binaries, has a simple memory model, and its garbage collector is designed for low-latency workloads. For a service that needs to maintain hundreds of concurrent agent sessions with consistent response times, this predictability matters more than raw throughput.
The ecosystem gap is real, though. Go’s AI ecosystem is thin. No LangChain equivalent. Limited SDK support from major LLM providers (improving, but still behind). Building agent tooling in Go often means building from scratch — which is either a feature or a tax, depending on your perspective.
The honest assessment: Go is excellent for the orchestration and infrastructure layer — the part that manages concurrency, state, and reliability. It’s a poor choice for the experimentation layer — the part where you’re iterating on prompts, testing new tool patterns, and integrating with the latest framework of the week.
TypeScript: the middle path (and its hidden costs)
TypeScript occupies an interesting position. It’s typed (enough). It has a massive ecosystem. Everyone knows it. It feels like the pragmatic choice.
And for certain agent architectures, it is. If your agents live in a web stack — browser-based copilots, VS Code extensions, serverless functions — TypeScript is the natural choice. The Vercel AI SDK, LangChain.js, and Anthropic’s TypeScript SDK are all mature.
But there are trade-offs that the familiarity obscures.
The event loop is a ceiling. Node.js’s single-threaded event loop works beautifully for I/O-bound tasks. LLM API calls are I/O-bound. So far, so good. But agent systems increasingly need CPU-bound work too — parsing large context windows, running local embeddings, computing similarity scores, managing complex state machines. In Node, this blocks the event loop. Worker threads exist, but they’re clunky compared to Go’s goroutines or even Python’s multiprocessing.
“Typed enough” is a spectrum. TypeScript’s type system is powerful — arguably more expressive than Go’s. But it inherits JavaScript’s runtime, where types evaporate. The mismatch between compile-time guarantees and runtime reality creates a class of bugs specific to TypeScript: code that type-checks perfectly but fails when the LLM returns null where you expected string, because the runtime doesn't enforce the contract your types describe.
Dependency weight. A typical TypeScript agent project pulls in hundreds of transitive dependencies. Each one is a potential failure point, a potential security surface, and a potential breaking change. Go binaries are self-contained. Python dependencies are heavy but well-understood. The JavaScript ecosystem’s dependency graph is uniquely fragile for production infrastructure.
The polyglot thesis
Here’s where I’ve landed after building in both Go and Python, and evaluating TypeScript for specific use cases: mature agent systems will be polyglot not because engineers want them to be, but because the problem demands it.
The stack, in practice, looks something like this:
Infrastructure layer (Go): Session management, concurrency orchestration, shared state, decision graph execution, context lifecycle. This is the part that needs to be fast, correct, and reliable. It changes infrequently and runs for a long time.
Intelligence layer (Python): LLM integration, prompt management, tool definitions, evaluation pipelines, experimentation. This is the part that needs to iterate fast, access the latest models and frameworks, and be approachable for ML engineers who aren’t systems programmers.
Interface layer (TypeScript): If agents surface in web UIs, VS Code, or serverless endpoints, TypeScript handles the presentation and thin orchestration at the edge.
The boundaries between these layers aren’t arbitrary. They follow the fault lines of what each language does well:
Concern Go Python TypeScript Concurrency model Native, lightweight Bolted on (asyncio) Event loop (single-thread) Type safety at runtime Enforced Advisory Erased AI/ML ecosystem Thin Dominant Growing Long-running services Excellent Adequate Adequate Iteration speed Moderate Fast Fast Deployment simplicity Single binary Containers + deps Containers + deps
The question behind the question
When someone asks “which language should I use for agent infrastructure?”, they’re usually asking a deeper question: how seriously should I treat the non-LLM parts of my agent system?
If you treat the orchestration layer as disposable glue code — something you’ll rewrite when it breaks — then pick whatever gets you to a demo fastest. Python. No contest.
But if you’re building agent infrastructure that will run in production, serve multiple teams, maintain state across sessions, and scale beyond a single developer’s laptop — then you’re building a distributed system that happens to call LLMs. And distributed systems have opinions about language choice that predate the AI hype cycle by decades.
The wrong answer isn’t Go, or Python, or TypeScript. The wrong answer is “it doesn’t matter.”
It does. Choose deliberately.
Daniel Braz is CTO at BRQ Product & Experience Studios, where he leads digital product engineering with a focus on agentic systems and AI-assisted development workflows. He’s currently building agent infrastructure in both Go and Python — not because he enjoys maintaining two toolchains, but because the problem demands it.
Go, Python, or TypeScript for agent infrastructure? The wrong answer is “it doesn’t matter” was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.