- Add sdkDefaultBaseURL map covering the 14 npm SDKs that ship a
hard-coded baseURL (groq, cerebras, mistral, xai, perplexity,
togetherai, deepinfra, cohere, v0, aihubmix, venice, merge-gateway,
openrouter, vercel gateway), so providers whose models.dev entry
omits the api field still auto-route correctly.
- Extend npmToWireProtocol so these thin OpenAI-compatible wrappers
route through fantasy's openaicompat provider.
- Add resolveTemplatedAPIURL to substitute ${VAR} placeholders for
cloudflare-workers-ai, databricks, snowflake-cortex from the env,
with friendly errors that name the missing vars.
- Wire amazon-bedrock and azure-cognitive-services aliases into the
existing native handlers; add createGoogleVertexProvider for the
google-vertex case.
- Expose kit.ResolveProviderBaseURL in the public SDK so embedders
can introspect the effective endpoint before instantiating a Kit.
- Refresh embedded_models.json from models.dev (5113 -> 5121 models;
139 providers unchanged).
KIT SDK
The KIT SDK (pkg/kit) lets you embed Kit's full agent capabilities — LLM interactions, tool execution, session management, streaming, hooks — into any Go application.
Installation
go get github.com/mark3labs/kit
Basic Usage
package main
import (
"context"
"fmt"
"log"
kit "github.com/mark3labs/kit/pkg/kit"
)
func main() {
ctx := context.Background()
// Create Kit instance with default configuration
host, err := kit.New(ctx, nil)
if err != nil {
log.Fatal(err)
}
defer func() { _ = host.Close() }()
// Send a prompt
response, err := host.Prompt(ctx, "What is 2+2?")
if err != nil {
log.Fatal(err)
}
fmt.Println(response)
}
Configuration
The SDK behaves identically to the CLI:
- Loads configuration from
~/.kit.ymlby default - Creates default configuration if none exists
- Respects all environment variables (
KIT_*) - Uses the same defaults as the CLI
Each kit.New / kit.NewAgent call owns an isolated configuration store,
so constructing multiple Kit instances in the same process is safe — setting
the model, thinking level, or generation parameters on one never affects
another, and runtime mutators (SetModel, SetThinkingLevel) only touch the
owning instance. This makes subagent spawning and multi-Kit embedding race-free
without external synchronization.
Functional options (NewAgent)
For simple programmatic setups, kit.NewAgent is an ergonomic
functional-options front door over kit.New. Streaming is enabled by default;
pass kit.WithStreaming(false) to opt out.
host, err := kit.NewAgent(ctx,
kit.WithModel("anthropic/claude-sonnet-4-5-20250929"),
kit.WithSystemPrompt("You are a helpful assistant."),
kit.WithMaxTokens(8192),
kit.WithThinkingLevel("medium"),
kit.Ephemeral(), // in-memory session, no persistence
)
Helpers: WithModel, WithSystemPrompt, WithStreaming, WithMaxTokens,
WithThinkingLevel, WithTools, WithExtraTools, WithProviderAPIKey,
WithProviderURL, WithConfigFile, WithDebug, and Ephemeral. Option is
a plain func(*Options), so you can define your own. For fields without a
With* helper (MCPConfig, InProcessMCPServers, SessionManager, MCP task
tuning) construct an Options value and call kit.New.
Options
You can override specific settings:
host, err := kit.New(ctx, &kit.Options{
Model: "ollama/llama3", // Override model
SystemPrompt: "You are a helpful bot", // Override system prompt
ConfigFile: "/path/to/config.yml", // Use specific config file
MaxSteps: 10, // Override max steps
Streaming: ptrBool(true), // *bool: nil = unset (default true), &false = off
Quiet: true, // Suppress debug output
// Session options
SessionPath: "./session.jsonl", // Open specific session
Continue: true, // Resume most recent session
NoSession: true, // Ephemeral mode
// Tool options
Tools: []kit.Tool{kit.NewBashTool()}, // Replace default tool set
ExtraTools: []kit.Tool{myTool}, // Add alongside defaults
DisableCoreTools: true, // Use no core tools (0 tools)
// Configuration
SkipConfig: true, // Skip .kit.yml files (viper defaults + env vars still apply)
// Compaction
AutoCompact: true, // Auto-compact near context limit
// In-process MCP servers (map name → *kit.MCPServer)
InProcessMCPServers: map[string]*kit.MCPServer{
"docs": mcpSrv,
},
})
Advanced Usage
With Tool Callbacks
Monitor tool execution in real-time:
unsub := host.OnToolCall(func(e kit.ToolCallEvent) {
fmt.Printf("Calling tool: %s\n", e.ToolName)
})
defer unsub()
unsub2 := host.OnToolResult(func(e kit.ToolResultEvent) {
if e.IsError {
fmt.Printf("Tool %s failed: %s\n", e.ToolName, e.Result)
} else {
fmt.Printf("Tool %s succeeded\n", e.ToolName)
}
})
defer unsub2()
unsub3 := host.OnMessageUpdate(func(e kit.MessageUpdateEvent) {
fmt.Print(e.Chunk)
})
defer unsub3()
response, err := host.Prompt(
ctx,
"List files in the current directory",
)
Dynamic MCP Server Management
Add, remove, and list MCP servers at runtime:
// Add an MCP server at runtime
n, err := host.AddMCPServer(ctx, "github", kit.MCPServerConfig{
Command: "npx",
Args: []string{"-y", "@modelcontextprotocol/server-github"},
})
fmt.Printf("Loaded %d tools from MCP server\n", n)
// List connected MCP servers
for _, s := range host.ListMCPServers() {
fmt.Printf("%s: %d tools\n", s.Name, s.ToolCount)
}
// Disconnect a server and remove its tools
host.RemoveMCPServer("github")
In-Process MCP Servers
Register mcp-go servers that run in the same process — no subprocess spawning, no network I/O. This is ideal for custom tool servers implemented in Go:
import (
"github.com/mark3labs/mcp-go/mcp"
"github.com/mark3labs/mcp-go/server"
)
// Create an mcp-go server with tools
mcpSrv := server.NewMCPServer("my-tools", "1.0.0",
server.WithToolCapabilities(true),
)
mcpSrv.AddTool(mcp.NewTool("search_docs",
mcp.WithDescription("Search documentation"),
mcp.WithString("query", mcp.Required()),
), searchHandler)
// Option 1: At init time via Options
host, _ := kit.New(ctx, &kit.Options{
InProcessMCPServers: map[string]*kit.MCPServer{
"docs": mcpSrv,
},
})
// Option 2: At runtime
n, err := host.AddInProcessMCPServer(ctx, "docs", mcpSrv)
fmt.Printf("Loaded %d tools from in-process server\n", n)
Kit does not take ownership of the server's lifecycle — the caller is responsible for any cleanup. In-process server tools are prefixed the same way as external MCP servers (e.g. "docs__search_docs").
MCP Prompts
MCP servers can expose prompt templates via the MCP prompts capability. Kit exposes these through the SDK:
// List prompts from all connected MCP servers
prompts := host.ListMCPPrompts()
for _, p := range prompts {
fmt.Printf("%s/%s: %s\n", p.Server, p.Name, p.Description)
}
// Get a specific prompt with arguments
msg, err := host.GetMCPPrompt(ctx, "server-name", "prompt-name", map[string]string{
"topic": "concurrency",
})
MCP Tasks (long-running tools)
Kit advertises MCP task support
during initialize. Cooperating servers can respond to tools/call with a
taskId immediately; Kit then polls tasks/get / tasks/result until the
task reaches a terminal state, and best-effort tasks/cancels on context
cancellation. Servers that don't advertise the capability keep their previous
synchronous behaviour.
host, _ := kit.New(ctx, &kit.Options{
// Per-server mode: auto (default), never, or always.
MCPTaskMode: map[string]kit.MCPTaskMode{
"build-server": kit.MCPTaskModeAlways,
},
MCPTaskTimeout: 15 * time.Minute, // total wall-clock cap
MCPTaskProgress: func(p kit.MCPTaskProgress) {
log.Printf("%s/%s: %s", p.Server, p.TaskID, p.Status)
},
})
// Inspect / cancel in-flight tasks
tasks, _ := host.ListMCPTasks(ctx, "build-server")
t, _ := host.GetMCPTask(ctx, "build-server", tasks[0].TaskID)
if !t.Status.IsTerminal() {
_, _ = host.CancelMCPTask(ctx, "build-server", t.TaskID)
}
The progress handler fires once when a task is accepted and again on every
observed status transition; the final invocation always carries a terminal
status (MCPTaskStatusCompleted, MCPTaskStatusFailed, or
MCPTaskStatusCancelled). Don't block in the handler — dispatch long work on
a goroutine.
Session Management
Maintain conversation context:
// First message
host.Prompt(ctx, "My name is Alice")
// Second message (remembers context)
response, _ := host.Prompt(ctx, "What's my name?")
// Response: "Your name is Alice"
// Clear conversation history
host.ClearSession()
Runtime Skills and Context Files
For multi-tenant chatbots, web services, or any host that needs per-user or
per-session instructions, the SDK lets you add, remove, and replace skills and
project context files (e.g. AGENTS.md) after Kit construction. Every
mutation recomposes the system prompt and applies it to the agent so the next
turn picks up the new instructions — no restart required.
// Add a programmatic skill (no file on disk required).
host.AddSkill(&kit.Skill{
Name: "polite-french",
Description: "Respond in French and always greet the user.",
Content: "Always reply in French. Open every response with 'Bonjour'.",
})
// Or load one from disk.
host.LoadAndAddSkill("/var/skills/refund-policy.md")
// Swap per-user AGENTS.md content fetched from your database.
host.AddContextFileContent(
fmt.Sprintf("session://%s/AGENTS.md", userID),
rulesFromDB,
)
// Tear down session-specific state when the user logs off.
host.RemoveSkill("polite-french")
host.RemoveContextFile(fmt.Sprintf("session://%s/AGENTS.md", userID))
// Or replace the whole set in one shot.
host.SetSkills(activeSkillsForUser)
host.SetContextFiles(activeContextForUser)
Readers (GetSkills, GetContextFiles) return snapshots, and every mutator
is safe to call concurrently from multiple goroutines.
Re-exported Types
The SDK re-exports message/session/MCP types so you don't need direct internal imports. Agent-configuration types are Kit-owned (not aliases) and use only SDK types in their signatures, so consumers never need to import the underlying LLM-provider package.
// Message types
kit.Message, kit.MessageRole, kit.ContentPart
kit.TextContent, kit.ReasoningContent, kit.ToolCall, kit.ToolResult, kit.Finish
kit.RoleUser, kit.RoleAssistant, kit.RoleTool, kit.RoleSystem
// LLM types — Kit-owned `LLM*` aliases over the underlying provider types,
// so consumers never import the provider package directly
kit.LLMMessage // {Role LLMMessageRole, Content string}
kit.LLMMessageRole // "user" | "assistant" | "system" | "tool"
kit.LLMUsage // {InputTokens, OutputTokens, TotalTokens, ...}
kit.LLMResponse // {Content, FinishReason, Usage}
kit.LLMFilePart // {Filename, Data []byte, MediaType}
// Agent configuration — concrete Kit-owned structs and function types.
// All fields use SDK types (e.g. `[]kit.Tool`), so consumers can construct
// these without importing any LLM-provider package.
kit.AgentConfig // Lower-level agent config — prefer Options unless you need direct control
kit.DebugLogger // Interface: LogDebug(string) / IsDebugEnabled() bool
kit.MCPTaskConfig // Task-aware MCP tools/call config (modes, polling, progress)
kit.ToolCallHandler // func(toolCallID, toolName, toolArgs string)
kit.ToolExecutionHandler // func(toolCallID, toolName, toolArgs string, isStarting bool)
kit.ToolResultHandler // func(toolCallID, toolName, toolArgs, result, metadata string, isError bool)
kit.ResponseHandler // func(content string)
kit.StreamingResponseHandler // func(content string)
kit.ToolCallContentHandler // func(content string)
kit.SpinnerFunc // func(fn func() error) error
// MCP OAuth types
kit.MCPServer // *server.MCPServer for in-process MCP transport
kit.MCPServerConfig // Configuration for an MCP server (stdio, SSE, or in-process)
kit.MCPAuthHandler // Interface: handles user-facing OAuth authorization
kit.DefaultMCPAuthHandler // Port + callback-server mechanics; set OnAuthURL for presentation
kit.CLIMCPAuthHandler // CLI wrapper: opens browser, prints status
kit.MCPTokenStore // Persists OAuth tokens for a single MCP server
kit.MCPToken // OAuth token (access token, refresh token, expiry)
kit.MCPTokenStoreFactory // Creates an MCPTokenStore for a given server URL
// Conversion helpers
msgs := kit.ConvertToLLMMessages(&msg) // SDK Message → []LLMMessage
msg := kit.ConvertFromLLMMessage(lMsg) // LLMMessage → SDK Message
API Reference
Types
Kit- Main SDK typeOptions- Configuration optionsOption- Functional option (func(*Options)) forNewAgentMessage- Conversation message with typed content partsTool- Agent tool interfaceTurnResult- Full result from a prompt including usage stats
Key Methods
New(ctx, opts)- Create new Kit instanceNewAgent(ctx, ...Option)- Create a Kit via functional options (streaming on by default)Prompt(ctx, message)- Send message and get response stringPromptResult(ctx, message)- Send message and get full TurnResultPromptWithOptions(ctx, message, opts)- Prompt with per-call optionsSteer(ctx, instruction)- System-level steeringFollowUp(ctx, text)- Continue without new user inputSetModel(ctx, model)- Switch model at runtimeGetModelString()- Get current model stringGetModelInfo()- Get model capabilities and limitsClearSession()- Clear conversation historyGetSessionPath()- Get session file pathGetSessionID()- Get session UUIDAddSkill(*Skill)/LoadAndAddSkill(path)/RemoveSkill(name)/SetSkills([])- Manage skills at runtimeAddContextFile(*ContextFile)/AddContextFileContent(path, content)/LoadAndAddContextFile(path)/RemoveContextFile(path)/SetContextFiles([])- Manage AGENTS.md-style context files at runtimeRefreshSystemPrompt()- Re-apply the composed system prompt to the agentClose()- Clean up resources
Options
Key Options fields for SDK usage:
| Field | Description |
|---|---|
Model |
Override model (e.g., "anthropic/claude-sonnet-4-5-20250929") |
SystemPrompt |
Override system prompt |
ConfigFile |
Load specific config file (empty = search defaults) |
SkipConfig |
Skip .kit.yml loading (defaults + env vars still apply) |
Tools |
Replace core tools with custom set |
ExtraTools |
Add tools alongside defaults |
DisableCoreTools |
Use no core tools (0 tools, for chat-only) |
NoSession |
Ephemeral mode (no session persistence) |
SessionPath |
Open specific session file |
Continue |
Resume most recent session |
InProcessMCPServers |
Map of name → *kit.MCPServer for in-process MCP servers |
Debug |
Enable debug logging |
Environment Variables
All CLI environment variables work with the SDK:
KIT_MODEL- Override modelANTHROPIC_API_KEY- Anthropic API keyOPENAI_API_KEY- OpenAI API keyGEMINI_API_KEY- Google API key- etc.
License
Same as KIT CLI