title: “Microsoft Joins Google in Backing Go for AI Agents — OpenAI and Anthropic Lag”
image: /images/covers/2026-10-15-microsoft-joins-google-in-backing-go-for-ai-agents-openai-an.svg
date: 2026-10-15T09:00:00+00:00
author: “Punit Naran”
description: “Go has become the lingua franca of cloud infrastructure, and now Microsoft (alongside Google) is building its agent framework in Go — while OpenAI and Anthropic’s agent tooling is still Python-first. The Go lens: the agent infrastructure layer is a 10MB static binary with a goroutine per agent; the Python model layer is a 100MB runtime. The boundary is an API, not a language. The Go agent runtime, in ~60 lines of stdlib, is what the two companies are standardizing.”
tags: [“Go”, “Community”, “AI”, “Cloud”, “Agents”]
draft: false
The New Stack’s framing is a market story with a systems core: Go has become the lingua franca of cloud infrastructure (container orchestration, CI/CD pipelines, the entire operational layer of the cloud), and Microsoft — alongside Google — is now building its agent framework in Go, while OpenAI and Anthropic’s agent tooling is still Python-first. The headline is “Microsoft joins Google”; the substance is why Go is the right language for the infrastructure layer of the agent era, and why the Python-first incumbents are lagging on that specific axis (not on the ML axis, where Python is right).
This post is the systems case, made concrete with Go: what “the lingua franca of cloud infrastructure” actually means as a measurable property (and why Go maximizes it), the Python-vs-Go split that the agent era is making explicit (Python for the model, Go for the *infrastructure), the two concrete reasons OpenAI/Anthropic are Python-first on the agent tooling (and why that is a *lag, not a *preference), and the practical rule for anyone building an agent system that has to run in production.
What “the lingua franca of cloud infrastructure” actually means (and why Go maximizes it)
“Lingua franca” is not a vibe; it is a measurable property: *the language the shared operational layer of the cloud is written in. The cloud’s operational layer is the thing that runs between the user’s application and the *hardware: the container runtime (Docker, *containerd), the orchestrator (Kubernetes), the CI/CD system (the pipelines that build and *deploy), the service mesh, the service discovery, the load balancer, the observability stack (the metrics, the tracing, the logging). This layer is the "infrastructure" of the cloud, and it is overwhelmingly Go: Docker is Go, Kubernetes is Go, containerd is Go, etcd is Go, Prometheus is Go, Cilium is Go. The reason Go won that layer is the same reason it is the right language for the agent infrastructure layer: Go is the language that is cheap to run as a small binary on every node, cheap to compile to a single static binary (no runtime to *ship), cheap to read for a non-author (small *surface, readable *errors), and cheap to run at high concurrency (the goroutine model is the right model for a service that talks to many things at once).
The consequence for the agent era: the agent infrastructure layer is the same kind of thing as the cloud infrastructure layer — a service that runs on every node, talks to many things at once, and has to be cheap to run and cheap to read for the operator who maintains it. Go is the language that maximizes all four of those properties, which is why "Microsoft joins Google in backing Go for AI agents" is a real strategic move and not a marketing one.
flowchart LR
subgraph infra["the cloud's operational layer (the 'lingua franca')"]
A[Docker / containerd]
B[Kubernetes]
C[etcd]
D[Prometheus / observability]
E[Cilium / service mesh]
end
subgraph agents["the agent infrastructure layer (same shape)"]
F[agent runtime (per-node)]
G[agent orchestration / service discovery]
H[agent metrics / tracing]
end
infra -->|all Go| X[Go]
agents -->|Microsoft + Google now| X
style X fill:#1a3a1a
The one-line summary: the cloud’s operational layer is Go because Go is the language that is cheap as a per-node binary, cheap to read for a non-author, and cheap to run at high concurrency. The agent infrastructure layer is the same shape, which is why Microsoft and Google are building it in Go and not in Python.
The New Stack headline is “OpenAI and Anthropic lag,” and the lag is on one specific axis: *the infrastructure layer of the agent system. The reason is the Python-vs-Go split that the agent era is making explicit:
*Python is the right language for the model layer. The ML ecosystem (the training *frameworks, the inference *engines, the model *serving) is Python, and it is Python because the ML research community is Python. OpenAI and Anthropic are Python-first on the model layer because the model layer is where the ML ecosystem lives, and that is correct.
*Go is the right language for the infrastructure layer. The agent runtime (the thing that runs on every node, manages the agent’s lifecycle, talks to the model API, handles the tool *calls) is infrastructure, not ML. It has to run at high concurrency (many agents at *once), it has to be cheap to deploy as a small binary (no Python interpreter to *ship), and it has to be readable by the operator who maintains it (a *non-author). Go maximizes all three.
The lag is that OpenAI and Anthropic are still Python-first on the infrastructure layer *— their agent tooling is Python because it was written in the same language as the model layer (the path of least *resistance), and the convenience of one language for both layers is outweighing the infrastructure cost of a Python interpreter on every node. The New Stack is naming the lag because the infrastructure layer is where the agent system lives and dies (a Python interpreter on every node is a 100MB runtime that has to be kept *updated), and the Go answer is a 10MB static binary.
The pattern Microsoft (and Google) are standardizing is a small Go service that wraps the LLM call and exposes it as an endpoint the rest of the system talks to: the LLM is a dependency, not the runtime. The Go binary is what the rest of the system depends on; it runs a goroutine per concurrent agent and talks to the Python model service over gRPC/HTTP. The boundary is the API, not the language:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
| // The minimal "Go agent runtime": a per-node static binary that
// manages the agent lifecycle, talks to the Python model service
// over a simple JSON-over-HTTP boundary, and runs one goroutine per
// concurrent agent. This is the *shape* of what Microsoft/Google are
// standardizing: 10MB, no interpreter, a goroutine per agent.
//
// The model layer (the LLM) is Python — the ML ecosystem is Python,
// and that is *correct*. The Go runtime is the *caller* of the LLM,
// not the LLM's home. The boundary is the API.
package main
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"sync"
"time"
)
// predictRequest is the Go->Python boundary: one JSON document.
// The Python model service (the model layer) is the one that owns
// the weights, the batching, the sampling; the Go runtime is the
// one that owns the *lifecycle* — the thing that runs on every
// node and manages thousands of agents at once.
type predictRequest struct {
AgentID string
Instruction string
}
type predictResponse struct {
Reply string
LatencyMS int
}
// callModel is the single Go->Python seam: a plain HTTP POST to
// the model service, with a bounded timeout so one slow model call
// cannot wedge the agent's goroutine. This is the *only* place the
// two languages meet — everything else is Go on one side, Python on
// the other, and the *API* is the contract.
func callModel(ctx context.Context, req predictRequest) (predictResponse, error) {
body, _ := json.Marshal(req)
httpReq, err := http.NewRequestWithContext(ctx, "POST",
"http://model-service:50051/predict", bytes.NewReader(body))
if err != nil {
return predictResponse{}, err
}
httpReq.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: 30 * time.Second}
resp, err := client.Do(httpReq)
if err != nil {
return predictResponse{}, err
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return predictResponse{}, fmt.Errorf("model service: HTTP %d", resp.StatusCode)
}
raw, _ := io.ReadAll(io.LimitReader(resp.Body, 1<<20))
var out predictResponse
if err := json.Unmarshal(raw, &out); err != nil {
return predictResponse{}, err
}
return out, nil
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
// agentLoop is the per-agent goroutine
// agentLoop is the per-agent goroutine: take an instruction, call
// the model, dispatch the tool calls. The goroutine *is* the
// concurrency model — no event loop, no GIL, no asyncio; the Go
// runtime schedules it across all cores. This is the "many agents
// at once" property that makes Go the infrastructure-layer language.
func agentLoop(id string, ch <-chan predictRequest) {
for req := range ch {
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
out, err := callModel(ctx, predictRequest{AgentID: id, Instruction: req.Instruction})
cancel()
if err != nil {
fmt.Printf("agent %s: predict failed: %v\n", id, err)
continue // the loop survives one bad call; the agent is not killed
}
fmt.Printf("agent %s: %q (latency %d ms)\n", id, out.Reply, out.LatencyMS)
}
}
// main wires the runtime: a channel of requests, a bounded pool of
// agent goroutines, and the model service on the other side of the
// API. This is the *entire* "agent infrastructure layer" in stdlib
// Go — no framework, no SDK, no interpreter to ship.
func main() {
reqs := make(chan predictRequest, 1024)
var wg sync.WaitGroup
for i := 0; i < 4; i++ { // 4 concurrent agents; scale as needed
id := fmt.Sprintf("agent-%d", i)
wg.Add(1)
go func() {
defer wg.Done()
agentLoop(id, reqs)
}()
}
// In production this channel is fed by an HTTP/gRPC server;
// for the demo we feed it a bounded burst and let the pool drain.
for i := 0; i < 8; i++ {
reqs <- predictRequest{Instruction: fmt.Sprintf("task %d", i)}
}
close(reqs)
wg.Wait()
}
```
The *point* is not the line count — it is that **the *infrastructure* layer is a *10MB* *static* *binary* *per* *node* *with* *a* *goroutine* *per* *concurrent* *agent*, *and* *the* *model* layer *is* *Python* *on* *the* *other* *side* *of* *an* *API.** *The* *boundary* *is* *the* *API,* *not* *a* *language* *barrier.
### The two layers, as a sequence
```mermaid
sequenceDiagram
participant N as Node (Go runtime, 10MB static)
participant G as Agent goroutine (one per concurrent agent)
participant M as Model service (Python, the ML ecosystem)
N-->>G: spawn goroutine for agent-N
G-->>M: POST /predict (JSON: agent-id + instruction)
M--->>G: 200 OK (reply + latency)
G-->>G: dispatch tool calls, update state, reply
Note over N,M: the boundary is the API; the language is an implementation detail
```
## Why the Python-first incumbents are "lagging" (and why it is not a Python problem)
The New Stack is careful not to say "Python is bad"; it is saying "**Python-first on the *infrastructure* layer is a *lag.*" The reason it is a lag is the *three infrastructure costs* of a Python interpreter on *every* node:
1. **The *runtime* *cost:** *a* *Python* *interpreter* *is* *a* *100MB* *runtime* *that* *has* *to* *be* *shipped* *to* *every* *node,* *kept* *updated* (the *security* *patches), *and* *started* *on* *every* *boot.* *A* *Go* *binary* *is* *10MB* *and* *static* (no *runtime* *to* *ship). *At* *the* *scale* *of* *a* *cloud* *with* *thousands* *of* *nodes,* *the* *100MB* *times* *the* *node* *count* *is* *a* *real* *cost.*
2. **The* *concurrency* *cost:** *Python's* *GIL* *means* *a* *Python* *process* *cannot* *use* *more* *than* *one* *core* *for* *CPU-bound* *work,* *and* *the* *async* *model* *is* *a* *separate* *concern* (the *event* *loop). *Go's* *goroutine* *model* *is* *the* *native* *high-concurrency* *model: *a* *goroutine* *per* *agent* *is* *cheap* (a *few* *KB* *of* *stack), *and* *the* *runtime* *schedules* *them* *across* *all* *cores* *without* *an* *event* *loop.* *For* *a* *service* *that* *manages* *thousands* *of* *agents* *at* *once,* *the* *goroutine* *model* *is* *the* *right* *model.*
3. **The* *readability* *cost:** *the* *operator* *who* *maintains* *the* *infrastructure* *layer* *is* *a* *non-author* (they *did* *not* *write* *the* *code). *Go's* *small* *surface* *and* *readable* *errors* *make* *the* *reading* *cost* *low; *Python's* *dynamic* *typing* *and* *the* *metaclass* *and* *decorator* *and* *`__init__` *surface* *make* *the* *reading* *cost* *higher* *for* *a* *non-author.* *The* *infrastructure* *layer* *is* *read* *by* *operators* *at* *3am,* *and* *the* *reading* *cost* *is* *the* *cost.*
| Company | Go-for-AI posture | What it standardized |
|---|---|---|
| Google | Go is the *default* for LLM *serving* (the model runs on Go infra) | the *inference* side |
| Microsoft | Go for the *agent* layer (the *caller* of the LLM) | the *agent* side |
| OpenAI / Anthropic | Python-first, Go a second-order choice | the *training* side (not Go's) |
The split is the whole story: **Go owns the *serving* and the *agent* layer, while Python owns *training.*** The "lag" isn't that OpenAI and Anthropic don't use Go — it's that their *primary* workloads (training, data pipelines) are Python-native, so Go never becomes the *default* there.
> **Note**: "Go for AI agents" is a *serving-and-orchestration* claim, not a *training* claim. The bet is that the *hot path* of an agent (the *HTTP* layer, the *tool* calls, the *state*) is Go's sweet spot, and the *training* (where Python rules) is a *separate* system the agent *talks to*, not *lives in*.
> **Warning**: the "Go is the agent language" narrative is *vendor-shaped*. Both Google and Microsoft have a *business* reason to prefer Go for the *serving* layer (it's their *infra* language), and the *training* workloads — where Python's dominance is *real* and *uncontested* — are *not* where the Go bet lands. Take the "Go for AI" claim at its *serving*-layer value, not as a *training*-language claim.
## Takeaways
- **The lingua franca of cloud infrastructure is Go** because Go is the language that minimizes the *three* infrastructure costs (the per-node runtime cost, the concurrency cost, the reading cost). Docker, Kubernetes, etcd, Prometheus, Cilium are *all* Go, and that is the *reason*.
- **The agent era has *two* layers, and they want *different* languages:** the *model* layer is *Python* (the ML ecosystem), and the *infrastructure* layer is *Go* (the operational layer). The *boundary* is *an* *API* (gRPC/HTTP), *not* a *language* *barrier.
- **OpenAI and Anthropic are Python-first on the *infrastructure* layer** because the *model* layer is *Python* and the *path* *of* *least* *resistance* is *one* *language* *for* *both.* *The* *lag* *is* *the* *three* *infrastructure* *costs* *of* *a* *Python* *interpreter* *on* *every* *node* (the *100MB* *runtime, *the* *GIL* *concurrency* *cost, *the* *reading* *cost).
- **The practical rule for a production agent system:** the *model* layer is *Python*, the *infrastructure* layer is *Go*, the *boundary* is *an* *API.* *The* *infrastructure* *layer* *is* *a* *10MB* *static* *binary* *per* *node* *with* *a* *goroutine* *per* *concurrent* *agent.* *The* *operator* *reads* *that* *code* *at* *3am,* *and* *the* *reading* *cost* *is* *the* *cost.*
## Next steps
1. **Read the New Stack article in full** for the *specific* Microsoft agent-framework Go announcement and the *OpenAI/Anthropic* Python-first comparison. The *one-liner* is the *thesis*; *the* *article* *is* *the* *evidence.*
2. **If you are building an agent system, split the two layers explicitly: Python for the model, Go for the infrastructure.** *The* *boundary* *is* *a* *gRPC/HTTP* *API.* *The* *infrastructure* *layer* *is* *a* *small* *static* *binary* *per* *node.*
3. **If you are running a Python-first agent infrastructure in production, measure the three costs** (the *per-node* *runtime* *size, *the* *concurrency* *ceiling* *under* *the* *GIL, *the* *operator's* *reading* *cost) *and* *price* *the* *Go* *alternative.* *The* *delta* *is* *the* *lag* *the* *New* *Stack* *is* *naming.*
4. **Do not read "Go for AI" as "Go for ML."** The *training* workloads — where Python's dominance is *real* and *uncontested* — are *not* where the Go bet lands. The Go bet is the *serving* and *agent* layer, and it is a *serving*-layer claim.
|