Model or dataset
Ingenimax/agent-sdk-go avatar
Ingenimax/agent-sdk-go

agent-sdk-go: A Go Agent Framework Where Tenancy and Memory Are Context Values

A powerful Go framework for building production-ready AI agents!

630 stars132 forksGoMIT

At a glance

What is it?
Ingenimax's agent-sdk-go wires multi-LLM clients, tool registries, memory backends and multi-tenancy into a single Go package tree, with a headless CLI alongside it. The design is opinionated in ways that matter: organization and conversation identity travel through context.Context, and configuration resolves through a global accessor rather than explicit construction.
Who is it for?
Adopt it if you are building Go services that need multiple LLM providers behind one interface and you are comfortable passing org and conversation identity through context.Context, because that pattern is baked into the Run path rather than optional.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The Problem: Assembling an Agent Stack in Go Without Gluing Five Libraries

Building an agent in Go usually means assembling separate pieces: an HTTP client per LLM vendor, a tool dispatch layer, a conversation store, a tracing hook, and some way to keep two customers' data apart. Each piece has its own interface conventions, and the seams between them are where the bugs live. agent-sdk-go's stated goal is to collapse that assembly into one module. The README describes it as integrating "memory management, tool execution, multi-LLM support, and enterprise features into a flexible, extensible architecture."

The audience is Go teams shipping agent behaviour inside an existing service, not people prototyping in a notebook. Two details point at that. First, the multi-tenancy package is a first-class import in the basic example, not an add-on. Second, the SDK ships a headless CLI (agent-cli) in addition to the library, which suggests the maintainers expect the same agent definitions to be run both inside a program and from a shell. If you are writing a one-off script that calls one model, this framework is more structure than the task needs.

How agent-sdk-go Is Put Together: Client, Registry, Memory, Context

The README example shows the composition pattern. You construct an LLM client (openai.NewClient with the API key and options such as openai.WithLogger), a memory backend (memory.NewConversationBuffer), and a tools.Registry, then hand all three to agent.NewAgent through functional options: WithLLM, WithMemory, WithTools, WithSystemPrompt, WithName. The registry is built by registering individual tools, for example websearch.New(apiKey, searchEngineID) guarded by a check that both the Google API key and search engine ID are non-empty. Tools are then passed as a slice via .List().

The part worth studying is how identity reaches the agent at call time. The example builds a context with two separate mechanisms:

ctx = multitenancy.WithOrgID(ctx, "default-org") ctx = context.WithValue(ctx, memory.ConversationIDKey, "conversation-123")

That context is then passed to agent.Run. So the organization boundary and the conversation boundary are both carried as context values rather than as arguments to Run or fields on the agent. This is the central architectural decision in the SDK. It means one agent instance can serve many tenants and many conversations, and the memory layer can key its storage off whatever the context carries. It also means the compiler will not help you if you forget to set the org ID; the failure surfaces at runtime, inside the memory or tenancy layer, not at the call site. The README does not document what happens when WithOrgID is omitted, and that is a gap worth closing before production use.

Getting It Running: go get, agent-cli init, and the Environment Variables That Matter

As a library, installation is a single command: go get github.com/Ingenimax/agent-sdk-go. The README lists Go 1.23+ as the prerequisite and notes Redis as optional, used for distributed memory.

As a CLI, there are three paths. Pre-built binaries are downloadable from the GitHub releases page. Alternatively, go install github.com/Ingenimax/agent-sdk-go/cmd/agent-cli@latest. Or clone the repository and run make build-cli, with make install to put it on the system PATH.

The CLI workflow starts with agent-cli init to generate configuration, then either exporting OPENAI_API_KEY directly or copying env.example to .env. From there, agent-cli run "What's the weather in San Francisco?" executes a single query and agent-cli chat opens an interactive session. Note that the CLI example uses the same weather question as the Go example, which implies the CLI's bootstrap configuration includes a web search tool wired the same way.

Configuration comes from environment variables, and the README names four: OPENAI_API_KEY, OPENAI_MODEL (with gpt-4o-mini as the example value), LOG_LEVEL (debug, info, warn, error) and REDIS_ADDRESS. It points to .env.example for the complete list rather than enumerating it. In Go code, configuration is retrieved through config.Get(), which returns a struct with nested fields such as cfg.LLM.OpenAI.APIKey and cfg.Tools.WebSearch.GoogleSearchEngineID. That global accessor is the second opinionated choice in the SDK: it means package-level state, and the README example calls config.Get() twice, once in main and once inside createTools, rather than threading the config through function arguments. For tests, that pattern is awkward unless the config package offers a way to set the global explicitly, which the material shown here does not describe.

MCP, YAML Definitions and the Bootstrapping Claim

Three features in the README deserve separate scrutiny because they are the ones most likely to drive an adoption decision.

MCP support is bidirectional in an unusual way. The SDK can act as an MCP client against servers over HTTP and stdio transports, per the feature list. Separately, the project runs its own MCP server, called Nina, at https://nina.agentgogo.app/mcp using SSE transport, which you register in Cursor via ~/.cursor/mcp.json or in Claude Desktop via claude_desktop_config.json. Nina exposes three tools: ask_nina, search_sdk and get_sdk_status. The first two are documentation retrieval; get_sdk_status reports the state of Nina's knowledge base. This is a support channel, not a runtime dependency, and it is worth being clear about that distinction when evaluating the framework itself.

Declarative configuration is described as defining agents and tasks in YAML. The README does not show a YAML example, so the schema is unverifiable from this material. The same applies to the "zero-effort bootstrapping" claim that complete agent configurations can be auto-generated from a system prompt, and to the structured task framework's plan/approve/execute flow. All three are listed as features without accompanying code. Treat them as claims to verify against docs.goagents.dev before you design around them.

Token usage tracking is listed as built-in for cost monitoring. The README does not say whether counts come from provider-reported usage or local tokenisation, and those two approaches diverge enough in accuracy that the answer matters if you bill on it.

Where agent-sdk-go Is the Wrong Choice

The global config accessor is the sharpest limitation. config.Get() returning process-wide state works fine in a binary where you set environment variables once. It fits poorly in a library that a host application embeds, where the host may already own configuration, and it makes parallel tests with different settings hard to express. The README's own example calls Get() in two places, which is a sign the pattern propagates.

Context-carried tenancy has a matching failure mode. Because org ID and conversation ID are set with multitenancy.WithOrgID and context.WithValue respectively, a caller that builds its context in one place and runs the agent in another can silently drop the tenant. Nothing in the type signature prevents it. In a request-scoped web handler this is manageable; in code that spawns goroutines and reconstructs contexts, it is a place to be careful.

The CLI is a second consideration. It is described as a headless SDK, and the installation instructions offer pre-built binaries, go install and make build-cli. If your deployment is a container built from a Go module, pulling a separate CLI binary adds an artifact to track. If your deployment is a shell script or a cron job, the CLI is the shorter path.

Finally, the release cadence is a signal about API stability. Three releases (v0.2.67, v0.2.68, v0.2.69) landed within about three days in September 2026, all at the 0.2.x level. The major version is still zero. That is normal for a young framework and it is not a criticism of quality, but it does mean a go.mod require line pointing at the module without a pinned patch version will move under you.

The Alternative: LangChainGo and What Changes

The obvious comparison in Go is LangChainGo (github.com/tmc/langchaingo). The difference in approach is structural rather than feature-by-feature. LangChainGo organises around chains and an explicit runnable composition model: you build a pipeline of components and pass values through it, and multi-tenancy is something you implement in your own storage layer rather than something the library threads through context. agent-sdk-go inverts that. The agent is the unit, it owns its LLM, memory and tools, and per-request identity is injected through context.Context at Run time.

That inversion has consequences in both directions. With agent-sdk-go you get a pre-built agent abstraction and tenancy plumbing you do not have to write, at the cost of accepting the context-value convention and the global config accessor. With LangChainGo you get a more granular composition model and more freedom in how state is passed, at the cost of assembling the agent loop, the memory keying and the tenant isolation yourself. If your requirement is "one agent object, many tenants, minimal glue," agent-sdk-go's shape is closer to the problem. If your requirement is "compose retrieval, reranking and generation in a custom order," the chain model is a better fit.

A narrower alternative is to skip the framework entirely and call the provider SDKs directly with a small tool-dispatch switch. For a single-provider agent with two or three tools, that is less code than adopting either framework, and it removes the upgrade obligation. The multi-LLM abstraction in agent-sdk-go only pays for itself once you actually need to swap or route between OpenAI, Anthropic and Vertex AI.

Licence, Maintenance and Upgrade Cost

The repository is MIT licensed, which permits commercial use, modification and redistribution provided the copyright notice and permission notice are retained. That is the permissive end of the spectrum and imposes no copyleft obligation on your own code. This is a description of the licence text, not legal advice; if you are redistributing the SDK in a product, have counsel confirm the notice requirements.

Maintenance cost is dominated by the release cadence. The repository is not archived, the last push is dated 2026-09-07, and the three most recent releases cluster in early September 2026 at v0.2.x. For a Go dependency, the practical mitigation is to pin an exact patch version in go.mod and upgrade deliberately rather than tracking main. Because the framework sits between your code and three LLM providers, an upgrade can change behaviour in the agent loop even when the SDK's own API is unchanged, and the README does not describe a compatibility policy or a changelog format. Check the release notes for each version before moving the pin.

One dependency deserves attention at upgrade time: Redis, listed as optional for distributed memory. If you use it, REDIS_ADDRESS is the configuration key, and the memory backend choice (buffer versus vector retrieval) determines whether Redis is needed at all. The README names both memory modes but does not state which one requires Redis, so confirm that against docs.goagents.dev before you provision infrastructure for it.

Editorial conclusion

Adopt it if you are building Go services that need multiple LLM providers behind one interface and you are comfortable passing org and conversation identity through context.Context, because that pattern is baked into the Run path rather than optional. Avoid it if you need a stable API surface: the release history shows v0.2.67, v0.2.68 and v0.2.69 all landing within roughly three days in early September 2026, which is patch-level churn at a rate that argues against pinning loosely. Before committing, verify three things in the repository: whether pkg/config exposes a way to inject configuration without the global Get accessor, whether the vector memory backend requires Redis or has an in-process option, and what the guardrails package actually enforces versus what it only names.

Official sources

  1. Ingenimax/agent-sdk-go on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Community notes

Community notes