Files
kit/pkg/kit
Ed Zynda 06bf6d087a feat(models): resolve SDK default URLs for all registered providers
- 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).
2026-06-07 14:06:05 +03:00
..

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.yml by 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 type
  • Options - Configuration options
  • Option - Functional option (func(*Options)) for NewAgent
  • Message - Conversation message with typed content parts
  • Tool - Agent tool interface
  • TurnResult - Full result from a prompt including usage stats

Key Methods

  • New(ctx, opts) - Create new Kit instance
  • NewAgent(ctx, ...Option) - Create a Kit via functional options (streaming on by default)
  • Prompt(ctx, message) - Send message and get response string
  • PromptResult(ctx, message) - Send message and get full TurnResult
  • PromptWithOptions(ctx, message, opts) - Prompt with per-call options
  • Steer(ctx, instruction) - System-level steering
  • FollowUp(ctx, text) - Continue without new user input
  • SetModel(ctx, model) - Switch model at runtime
  • GetModelString() - Get current model string
  • GetModelInfo() - Get model capabilities and limits
  • ClearSession() - Clear conversation history
  • GetSessionPath() - Get session file path
  • GetSessionID() - Get session UUID
  • AddSkill(*Skill) / LoadAndAddSkill(path) / RemoveSkill(name) / SetSkills([]) - Manage skills at runtime
  • AddContextFile(*ContextFile) / AddContextFileContent(path, content) / LoadAndAddContextFile(path) / RemoveContextFile(path) / SetContextFiles([]) - Manage AGENTS.md-style context files at runtime
  • RefreshSystemPrompt() - Re-apply the composed system prompt to the agent
  • Close() - 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 model
  • ANTHROPIC_API_KEY - Anthropic API key
  • OPENAI_API_KEY - OpenAI API key
  • GEMINI_API_KEY - Google API key
  • etc.

License

Same as KIT CLI