Summary
When a declarative Agent runs on the Go ADK runtime (runtime: go) with long-term memory enabled (OpenAI embedding provider), save_memory fails at embedding generation with HTTP 401 invalid_issuer. Nothing is persisted, so cross-session load_memory returns memories: null.
The exact same agent config on the Python runtime works — the embedding call to api.openai.com/v1/embeddings returns 200 and the memory is saved. Since the default declarative runtime is now go, memory-enabled agents silently stop persisting memory.
Environment
- kagent OSS
v0.10.0-beta1
- Go runtime image:
cr.kagent.dev/kagent-dev/kagent/golang-adk@sha256:0be1b7a0fe9560b097351cd97c2f71accf7f6f288fcdc0d5d6aae57e66d81b01
- Python runtime image:
cr.kagent.dev/kagent-dev/kagent/app@sha256:ed96ed74b55eaceb92aec97dd84a0f523645c7372e501db9a019b637c7f67ee5
- Embedding
ModelConfig: provider: OpenAI, model: text-embedding-3-small; key is a valid OpenAI service-account key (sk-svcacct-…)
Error (Go agent pod)
msg: Tool execution failed tool: save_memory caller: agent/agent.go:408
error: failed to generate embedding: API returned status 401: {
"error": {
"message": "Your authentication token is not from a valid issuer.",
"type": "invalid_request_error",
"code": "invalid_issuer",
"param": null
},
"status": 401
}
Root cause (narrowed)
The Go embedding path is go/adk/pkg/embedding/embedding.go → openAIProvider.generate(), which POSTs to <base_url | https://api.openai.com/v1>/embeddings with Authorization: Bearer os.Getenv("OPENAI_API_KEY") and dimensions: 768.
Everything that request depends on is valid — only the Go runtime fails:
| Test |
Result |
Configured key + {"model":"text-embedding-3-small","dimensions":768} → OpenAI embeddings, from host |
200 |
| Same request from a pod in the agent's namespace (same egress) |
200 |
| Python runtime agent, identical config → embeddings |
200, memory saved (httpx log: POST https://api.openai.com/v1/embeddings "HTTP/1.1 200 OK") |
| Chat completions with the same key (Go agent) |
works |
| Go runtime agent → embeddings |
401 invalid_issuer |
The Go and Python pods are identical for the embedding auth path — same config.json (model: openai/…, base_url ""; memory.embedding: {provider: openai, model: text-embedding-3-small}), same OPENAI_API_KEY sourced from the same secret, and no base_url/proxy/OBO env in either. The only difference is the runtime image.
The non-OpenAI error body shape ("status": 401 alongside the error object; code: invalid_issuer) suggests the Go runtime is sending a different Authorization token (or hitting a different endpoint) than the configured OpenAI key against api.openai.com, rather than the raw OPENAI_API_KEY that works everywhere else.
Reproduction
- Deploy a declarative
Agent with runtime: go and memory enabled, using an OpenAI embedding ModelConfig (text-embedding-3-small).
- Send a message that triggers
save_memory, e.g. "My favorite color is blue. Please remember that."
- Pod log shows
save_memory … failed to generate embedding: API returned status 401 … invalid_issuer; the memory table stays empty.
- Switch the same
Agent to runtime: python and repeat → the embedding call returns 200 and a row is persisted.
Expected
The Go ADK memory embedding path should use the same working OpenAI credential/endpoint as chat completions (and as the Python runtime), so save_memory persists memories.
Workaround
Pin memory-enabled agents to runtime: python.
🤖 Filed with Claude Code
Summary
When a declarative
Agentruns on the Go ADK runtime (runtime: go) with long-term memory enabled (OpenAI embedding provider),save_memoryfails at embedding generation with HTTP 401invalid_issuer. Nothing is persisted, so cross-sessionload_memoryreturnsmemories: null.The exact same agent config on the Python runtime works — the embedding call to
api.openai.com/v1/embeddingsreturns200and the memory is saved. Since the default declarative runtime is nowgo, memory-enabled agents silently stop persisting memory.Environment
v0.10.0-beta1cr.kagent.dev/kagent-dev/kagent/golang-adk@sha256:0be1b7a0fe9560b097351cd97c2f71accf7f6f288fcdc0d5d6aae57e66d81b01cr.kagent.dev/kagent-dev/kagent/app@sha256:ed96ed74b55eaceb92aec97dd84a0f523645c7372e501db9a019b637c7f67ee5ModelConfig:provider: OpenAI,model: text-embedding-3-small; key is a valid OpenAI service-account key (sk-svcacct-…)Error (Go agent pod)
Root cause (narrowed)
The Go embedding path is
go/adk/pkg/embedding/embedding.go→openAIProvider.generate(), which POSTs to<base_url | https://api.openai.com/v1>/embeddingswithAuthorization: Bearer os.Getenv("OPENAI_API_KEY")anddimensions: 768.Everything that request depends on is valid — only the Go runtime fails:
{"model":"text-embedding-3-small","dimensions":768}→ OpenAI embeddings, from host200200200, memory saved (httpx log:POST https://api.openai.com/v1/embeddings "HTTP/1.1 200 OK")401 invalid_issuerThe Go and Python pods are identical for the embedding auth path — same
config.json(model: openai/…, base_url "";memory.embedding: {provider: openai, model: text-embedding-3-small}), sameOPENAI_API_KEYsourced from the same secret, and nobase_url/proxy/OBO env in either. The only difference is the runtime image.The non-OpenAI error body shape (
"status": 401alongside theerrorobject;code: invalid_issuer) suggests the Go runtime is sending a different Authorization token (or hitting a different endpoint) than the configured OpenAI key againstapi.openai.com, rather than the rawOPENAI_API_KEYthat works everywhere else.Reproduction
Agentwithruntime: goandmemoryenabled, using an OpenAI embeddingModelConfig(text-embedding-3-small).save_memory, e.g. "My favorite color is blue. Please remember that."save_memory … failed to generate embedding: API returned status 401 … invalid_issuer; thememorytable stays empty.Agenttoruntime: pythonand repeat → the embedding call returns200and a row is persisted.Expected
The Go ADK memory embedding path should use the same working OpenAI credential/endpoint as chat completions (and as the Python runtime), so
save_memorypersists memories.Workaround
Pin memory-enabled agents to
runtime: python.🤖 Filed with Claude Code