agentkit

module
v0.19.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 1, 2026 License: MIT

README

agentkit

A batteries-included Go client for OpenAI-compatible endpoints.

Most "LLM clients" hand you a chat() call and stop. agentkit owns the tablestakes every real agent client re-implements anyway — so you don't have to wrap them yourself:

  • the tool-call loop — chat → tool_calls → execute → feed back → repeat
  • context compaction + LOD truncation to fit the window (the Shaper)
  • message / notification injection into an in-flight conversation
  • queued-message batching — N arrivals coalesce into one turn
  • lifting — async tool results (a slow tool parks the turn, resumes later)
  • schema validation with a fix loop, and server-side constrained decoding
  • notification lifecycle — supersede, clear, and pre-turn revalidation
  • turn lifecycle — OnTurnStart / OnTurnEnd with a typed reason, so a host can tell a terminal tool from a reply and a cancellation from a fault
  • compaction lifecycle — OnCompactionStart / OnCompactionComplete, so a host can say "compacting" while it happens and record the summary as the whole record of what was folded
  • a fair-share 429/backpressure retry that honors the server's retry_after

What agentkit does not own is orchestration — roles, a task DAG, scheduling, when/why to run. That's your harness's job. agentkit gives it a Session to drive and a few small interfaces to implement.

go get github.com/iodesystems/agentkit

Requires Go 1.26+.

Packages

package what it is dependencies
llm the streaming OpenAI-compatible chat client (tools, tool_choice, grammar, response_format, 429 retry) stdlib only
mcpmgr MCP server manager — spawn stdio MCP servers, discover tools, call them, per-thread scoping, secret files stdlib only
agent the tablestakes: Session.Turn loop, Shaper, injection, lifting, validation, notification lifecycle llm only
files a mountable file toolset — read, edit, write, grep, list (+ opt-in delete, move; read alone also lists a directory and, with grep, searches a file or a tree) rooted at one directory, with capped reads, exact-once edits and .gitignore-aware search (rg when on PATH) llm only

agentkit has no third-party dependencies at all — go.mod declares a module path, a Go version, and nothing else:

$ go list -m all
github.com/iodesystems/agentkit

That is a deliberate constraint, not a brag. This library is meant to sit at the bottom of somebody else's dependency tree, where every module it drags in is one the host cannot refuse — and where a go get -u in an unrelated corner can break a build nobody touched. It also keeps the supply-chain surface of an agent loop, which by construction executes tool calls, down to code in this repo.

Concretely: mcpmgr speaks JSON-RPC to MCP servers over stdio itself (jsonrpc.go + protocol.go, ~650 lines) rather than vendoring an MCP SDK, and agent.NewID mints RFC 4122 v4 UUIDs from crypto/rand.

llm and mcpmgr are also zero-internal-dep — use them standalone. agent imports only llm + stdlib; it never sees your storage model.

Quickstart — a tool-call loop in ~20 lines

client := llm.NewClient("https://llm.iodesystems.com", os.Getenv("AGENTKIT_API_KEY"), "Qwen3-6-27B-MPT")

store := newMyStore()                 // you implement agent.Store (6 methods)
store.Append(ctx, "s1", agent.Entry{Kind: agent.KindUser, Content: "Weather in Denver?"})

sess := &agent.Session{
    SessionID: "s1",
    System:    "You are a helpful assistant. Use tools when they help.",
    Store:     store,
    Runner:    client,                // *llm.Client satisfies agent.LLMRunner
    Tools:     myTools,               // []llm.ToolDef
    Dispatch:  myDispatch,            // func(ctx, llm.ToolCall) (string, error)
    OnAssistantToken: func(s string) { fmt.Print(s) },
}

res, err := sess.Turn(ctx)            // res.Reply + res.Compactions + res.Usage{Total, Active}

That Turn call streams the completion, dispatches every tool the model requests, feeds the results back, re-prompts, and returns when the model stops calling tools — batching any messages that queued in the meantime, shaping the context to fit the window, and reporting any compaction + the token tally.

Runnable example

examples/agentkit-demo is a CLI with one subcommand per feature, wired to iode's corrallm server at llm.iodesystems.com:

go run ./examples/agentkit-demo chat       # streaming + 429 backpressure retry
go run ./examples/agentkit-demo tools      # local Go tool-call loop
go run ./examples/agentkit-demo schema     # client-side validation + fix loop
go run ./examples/agentkit-demo grammar    # server-side constrained decoding
go run ./examples/agentkit-demo inject     # notification injection + batching
go run ./examples/agentkit-demo lift       # async tool results
go run ./examples/agentkit-demo notify     # supersede / clear / preparer
go run ./examples/agentkit-demo compact    # LOD truncation + compaction

The schema, inject, lift, notify, and compact demos are fully offline (they exercise the mechanics without the model). chat, tools, and grammar hit the live model — which is small and often busy. A 429 there is a feature demo, not a bug: the client honors the server's retry_after and keeps trying until --timeout.

Docs

  • docs/concepts.md — the core model: Store, Entry, Session, Shaper, the neutral seam.
  • docs/features.md — every tablestake, with code and the demo that shows it.
  • docs/provider.md — connecting to corrallm / any OpenAI-compatible endpoint; 429, grammar, response_format, api-key-as-priority.

Status

Pre-release. Module path github.com/iodesystems/agentkit is final; nothing else is, and there are no compatibility shims — things get edited in place.

Extracted from autowork3, which drives Session over Postgres event streams. dun, a coding-agent harness, is the second consumer and the more useful test of the seam: it implements Store over a local session file and composes three MCP servers, so anywhere it had to reach around the contract rather than wrap it is a place the contract is wrong.

License

MIT © IodeSystems

Directories

Path Synopsis
Package agent is agentkit's batteries-included agent client over an OpenAI-compatible endpoint.
Package agent is agentkit's batteries-included agent client over an OpenAI-compatible endpoint.
toolfmt
Package toolfmt provides a token-lean, information-preserving re-encoder for tool-call RESULTS before they enter an LLM's context.
Package toolfmt provides a token-lean, information-preserving re-encoder for tool-call RESULTS before they enter an LLM's context.
benchmarks
cmd
toolfmt command
Command toolfmt exposes the agent/toolfmt encoders as a stdin->stdout CLI.
Command toolfmt exposes the agent/toolfmt encoders as a stdin->stdout CLI.
examples
agentkit-demo command
Command agentkit-demo showcases every major agentkit capability against a live OpenAI-compatible endpoint (default: iode's corrallm at llm.iodesystems.com).
Command agentkit-demo showcases every major agentkit capability against a live OpenAI-compatible endpoint (default: iode's corrallm at llm.iodesystems.com).
Package files is a configurable file toolset an agent host mounts: read, edit, write, grep and list (delete and move opt-in), rooted at one directory.
Package files is a configurable file toolset an agent host mounts: read, edit, write, grep and list (delete and move opt-in), rooted at one directory.
Package llm is the OpenAI-compatible streaming chat client every agent role's Turn loop uses to reach the LLM.
Package llm is the OpenAI-compatible streaming chat client every agent role's Turn loop uses to reach the LLM.
Package loopdetector answers one question about a model's output: is it going round in a loop, and how many times has it gone round.
Package loopdetector answers one question about a model's output: is it going round in a loop, and how many times has it gone round.
mcpauth
Package mcpauth has the discovery steps an MCP client needs before it can run OAuth against a protected server (MCP authorization, 2025-06-18 and later):
Package mcpauth has the discovery steps an MCP client needs before it can run OAuth against a protected server (MCP authorization, 2025-06-18 and later):
Package proc is a long-running thing that produces output.
Package proc is a long-running thing that produces output.
Package ragnotify implements agent.DocFinder over an MCP retrieval server (e.g.
Package ragnotify implements agent.DocFinder over an MCP retrieval server (e.g.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL