moonorm
An ORM / SQL toolkit for MoonBit — a parameterized, injection-safe query builder, the way SQLAlchemy Core is for Python. Bound values become ? placeholders, never spliced into the SQL string.
moon add moonbitstack/moonkoog✶ The contract at a glance
let agent = AIAgent::new(client, model=@llm.deepseek_v4_flash, tool_registry=tools) let answer = agent.run("what is 2+3?") // requests a completion, runs every tool the model asks for, feeds the results // back, and returns the first plain-text reply - Koog's singleRunStrategy, walked // as a graph.
§Prompts and messages
The conversation model every client speaks: typed messages (system, user, assistant, tool call, tool result) and the builder that assembles them into the Prompt an LLM request carries.
enum Role
A conversation role. Koog 1.1.1 collapses to three: a tool exchange is carried as parts inside a user/assistant message, not as a fourth top-level role.
enum MessagePart
One typed piece of a message's content. Koog 1.1.1 moved off flat string content to an ordered list of MessageParts. A ToolCall carries its arguments as a JSON value (Koog keeps the raw JSON string; we keep it parsed); a ToolResult carries the exact string the model is shown.
struct Message
A single message: a role and its ordered content parts. finish_reason is the provider's stop reason on an assistant reply, None on a request message.
fn Message::system(text : String) -> Message
A plain system message.
fn Message::user(text : String) -> Message
A plain user message.
fn Message::assistant(text : String) -> Message
A plain assistant message.
fn Message::tool_result( tool~ : String, output~ : String, id? : String? = None, is_error? : Bool = false) -> Message
A user message carrying a single tool result (a ToolResult is a request part, so it rides a user message). What the agent loop appends after running a tool.
fn Message::text_content( self : Message, separator? : String = "\n") -> String
The concatenated text of every Text part, joined by separator (Koog's Message.textContent). Non-text parts contribute nothing.
fn Message::tool_calls(self : Message) -> Array[MessagePart]
The tool calls this message requests: its ToolCall parts, in order. Empty when the message is a plain text reply — the loop's signal to finish.
enum ToolChoice
How the model should use tools this request (Koog LLMParams.ToolChoice).
enum Schema
A structured-output schema the model must produce (Koog LLMParams.Schema): a named JSON schema, in the provider's basic or the JSON-Schema-standard dialect.
struct LLMParams
Per-request LLM parameters (Koog LLMParams). None means "let the provider default apply". This carries the full Koog surface; each client maps the subset its provider supports.
fn LLMParams::default() -> LLMParams
The empty params: no overrides.
struct Prompt
The immutable request object handed to an LLM: an ordered message list, an identifier, and the params. Koog builds it through a DSL; here it is built through the fluent PromptBuilder.
fn Prompt::append(self : Prompt, message : Message) -> Prompt
A copy of this prompt with message appended — the immutable-append the agent loop uses to grow the conversation without mutating a shared value.
struct PromptBuilder
A mutable builder for a Prompt. MoonBit has no receiver-lambda DSL, so the Koog prompt { system(...); user(...) } block becomes a fluent chain PromptBuilder::new().system(...).user(...).build().
fn PromptBuilder::new( id? : String = "prompt", params? : LLMParams = LLMParams::default()) -> PromptBuilder
A fresh builder.
fn PromptBuilder::system( self : PromptBuilder, text : String) -> PromptBuilder
Append a system message.
fn PromptBuilder::user( self : PromptBuilder, text : String) -> PromptBuilder
Append a user message.
fn PromptBuilder::assistant( self : PromptBuilder, text : String) -> PromptBuilder
Append an assistant message.
fn PromptBuilder::message( self : PromptBuilder, message : Message) -> PromptBuilder
Append a whole pre-built message (e.g. an assistant reply carrying tool calls).
fn PromptBuilder::tool_result( self : PromptBuilder, tool~ : String, output~ : String, id? : String? = None, is_error? : Bool = false) -> PromptBuilder
Append a user message carrying a single tool result (Koog's toolResult; a ToolResult is a request part, so it rides a user message).
fn PromptBuilder::params( self : PromptBuilder, params : LLMParams) -> PromptBuilder
Set the LLM params.
fn PromptBuilder::build(self : PromptBuilder) -> Prompt
Finish building.
§Models and the client contract
LLModel and the LLMClient trait an executor implements, plus the catalogues of published OpenAI, Anthropic, Google, DeepSeek and Mistral models with their capabilities.
struct LLMProvider
An LLM provider identity. Koog models LLMProvider as an *open* class, not a closed enum, because a user can define their own provider — so moonkoog uses a struct plus named constants rather than a variant set. Source: prompt/prompt-llm/.../llm/LLMProvider.kt.
let openai : LLMProvider =
let anthropic : LLMProvider =
let google : LLMProvider =
let deepseek : LLMProvider =
let alibaba : LLMProvider =
let meta : LLMProvider =
let ollama : LLMProvider =
let openrouter : LLMProvider =
let mistralai : LLMProvider =
enum LLMCapability
A capability a model may declare. Koog's LLMCapability is a sealed hierarchy; this flattens its leaves (the two JSON-schema levels become SchemaJsonBasic / SchemaJsonStandard; the two OpenAI endpoints become OpenAIEndpointCompletions / OpenAIEndpointResponses; Vision is a single leaf here rather than its image/video subtypes — those land when multimodal does). Source: prompt/prompt-llm/.../llm/LLMCapability.kt.
struct LLModel
A specific model: which provider serves it, its provider-side id, its declared capabilities, and the optional context / output-token limits. Source: prompt/prompt-llm/.../llm/LLModel.kt.
fn LLModel::supports(self : LLModel, capability : LLMCapability) -> Bool
Whether the model declares capability (Koog LLModel.supports).
let gpt_4o : LLModel =
GPT-4o — the versatile omni flagship (128k context, 16k output).
let gpt_4o_mini : LLModel =
GPT-4o mini — the cost-optimised 4o (128k context, 16k output).
let gpt_4_1 : LLModel =
GPT-4.1 — complex-task model (1,047,576 context, 32k output).
let gpt_4_1_nano : LLModel =
GPT-4.1 nano — smallest, cheapest 4.1 (1,047,576 context, 32k output).
let gpt_4_1_mini : LLModel =
GPT-4.1 mini — balanced 4.1 (1,047,576 context, 32k output).
let o1 : LLModel =
o1 — the reasoning model (200k context, 100k output).
let o3 : LLModel =
o3 — well-rounded reasoning across domains (200k context, 100k output).
let o3_mini : LLModel =
o3-mini — small reasoning model, no vision (200k context, 100k output).
let o4_mini : LLModel =
o4-mini — cost-effective reasoning (200k context, 100k output).
let gpt_5 : LLModel =
GPT-5 — flagship for coding, reasoning, agentic tasks (400k context, 128k output).
let gpt_5_mini : LLModel =
GPT-5 mini — faster, cheaper GPT-5 (400k context, 128k output).
let gpt_5_nano : LLModel =
GPT-5 nano — fastest, cheapest GPT-5 (400k context, 128k output).
let gpt_5_codex : LLModel =
GPT-5-Codex — agentic coding, Responses API only (400k context, 128k output).
let gpt_5_pro : LLModel =
GPT-5 pro — highest-compute reasoning, Responses API only (400k context, 272k output).
let gpt_5_1 : LLModel =
GPT-5.1 — flagship with configurable reasoning effort (400k context, 128k output).
let gpt_5_1_codex : LLModel =
GPT-5.1-Codex — agentic coding, Responses API only (400k context, 128k output).
let gpt_5_1_codex_max : LLModel =
GPT-5.1-Codex-Max — purpose-built agentic coding, Responses API only (400k context, 128k output).
let gpt_5_2 : LLModel =
GPT-5.2 — flagship for coding and agentic tasks (400k context, 128k output).
let gpt_5_2_pro : LLModel =
GPT-5.2 pro — Responses API only, no JSON schema (400k context, 128k output).
let gpt_5_2_codex : LLModel =
GPT-5.2-Codex — agentic coding, Responses API only, no JSON schema (400k context, 128k output).
let gpt_5_3_codex : LLModel =
GPT-5.3-Codex — agentic coding, Responses API only, no JSON schema (400k context, 128k output).
let gpt_5_4 : LLModel =
GPT-5.4 — frontier model for complex professional work (1,050,000 context, 128k output).
let gpt_5_4_mini : LLModel =
GPT-5.4 mini — faster GPT-5.4 for high-volume workloads (400k context, 128k output).
let gpt_5_4_nano : LLModel =
GPT-5.4 nano — speed/cost model for classification and sub-agents (400k context, 128k output).
let gpt_5_4_pro : LLModel =
GPT-5.4 pro — highest-compute GPT-5.4, Responses API only (1,050,000 context, 128k output).
let gpt_5_5 : LLModel =
GPT-5.5 — newest frontier model (1,050,000 context, 128k output).
let gpt_5_5_pro : LLModel =
GPT-5.5 pro — highest-compute GPT-5.5, Responses API only (1,050,000 context, 128k output).
let gpt_audio : LLModel =
GPT Audio — audio in and out (128k context, 16k output).
let gpt_4o_mini_audio : LLModel =
GPT-4o mini Audio — cheaper audio model (128k context, 16k output).
let gpt_4o_audio : LLModel =
GPT-4o Audio — audio in and out (128k context, 16k output).
let text_embedding_3_small : LLModel =
text-embedding-3-small — cost-effective embeddings (8191 context).
let text_embedding_3_large : LLModel =
text-embedding-3-large — highest-quality embeddings (8191 context).
let text_embedding_ada_002 : LLModel =
text-embedding-ada-002 — the older ada embeddings (8191 context).
let omni_moderation : LLModel =
omni-moderation — the most capable moderation model, text + image (32768 context).
fn openai_models() -> Array[LLModel]
The OpenAI models supported out of the box (Koog OpenAIModels.supportedModels), in the source's grouping order.
let claude_3_opus : LLModel =
Claude 3 Opus.
let claude_3_haiku : LLModel =
Claude 3 Haiku.
let claude_3_5_sonnet : LLModel =
Claude 3.5 Sonnet.
let claude_3_5_haiku : LLModel =
Claude 3.5 Haiku.
let claude_3_7_sonnet : LLModel =
Claude 3.7 Sonnet.
let claude_sonnet_4 : LLModel =
Claude Sonnet 4.
let claude_opus_4 : LLModel =
Claude Opus 4.
let claude_opus_4_1 : LLModel =
Claude Opus 4.1.
let claude_sonnet_4_5 : LLModel =
Claude Sonnet 4.5.
let gemini_2_0_flash_lite_001 : LLModel =
Gemini 2.0 Flash-Lite (specific version).
let gemini_2_5_pro : LLModel =
Gemini 2.5 Pro — advanced capabilities for complex tasks.
let gemini_2_5_flash : LLModel =
Gemini 2.5 Flash — a balance of speed and capability.
let gemini_2_5_flash_lite : LLModel =
Gemini 2.5 Flash-Lite — cost-efficient, high throughput.
let gemini_3_flash_preview : LLModel =
Gemini 3 Flash Preview — Pro-level intelligence at Flash speed.
let gemini_3_1_pro_preview : LLModel =
Gemini 3.1 Pro Preview — advanced reasoning.
let gemini_3_1_flash_lite_preview : LLModel =
Gemini 3.1 Flash-Lite Preview — low latency.
let gemini_3_1_flash_lite : LLModel =
Gemini 3.1 Flash-Lite — low latency.
let gemini_3_5_flash : LLModel =
Gemini 3.5 Flash — fast multimodal generation.
let gemini_embedding_001 : LLModel =
Gemini embedding model (text embeddings).
fn google_models() -> Array[LLModel]
The Google models supported out of the box (Koog GoogleModels.supportedModels), in the source's order.
let deepseek_v4_flash : LLModel =
DeepSeek V4 Flash — fast, cost-effective generation (also moonkoog's default smoke-test model).
let deepseek_v4_pro : LLModel =
DeepSeek V4 Pro — advanced reasoning and agentic tasks.
fn deepseek_models() -> Array[LLModel]
The DeepSeek models supported out of the box (Koog DeepSeekModels.supportedModels).
let mistral_medium_3 : LLModel =
Mistral Medium 3 — frontier-class multimodal (128k context).
let mistral_large_2_1 : LLModel =
Mistral Large 2.1 — top-tier model for high-complexity tasks (128k context).
let mistral_small_2 : LLModel =
Mistral Small 2 — efficient model for standard tasks (32k context).
let magistral_medium_1_2 : LLModel =
Magistral Medium 1.2 — frontier reasoning model with vision (128k context).
let codestral : LLModel =
Codestral — coding model for low-latency fill-in-the-middle and corrections (256k context).
let devstral_medium : LLModel =
Devstral Medium — enterprise coding model for software-engineering agents (128k context).
let mistral_embed : LLModel =
Mistral Embed — text embedding model (8k context).
let codestral_embed : LLModel =
Codestral Embed — code embedding model (8k context).
let mistral_moderation : LLModel =
Mistral Moderation — content-safety moderation model (8k context).
fn mistral_models() -> Array[LLModel]
The Mistral AI models supported out of the box (Koog MistralAIModels.supportedModels).
§Tools
A tool states its JSON schema through an explicit descriptor - MoonBit has no reflection to derive one from - and a ToolRegistry is what an agent is handed. The prebuilt file, shell and search tools are ready to register.
enum ToolParameterType
The JSON-schema type of a tool parameter. Koog's ToolParameterType is a sealed hierarchy; this is a faithful 1:1 sum. TList/TObject/TAnyOf recur. Source: agents/agents-tools/.../tools/ToolDescriptor.kt.
struct ToolParameterDescriptor
One named tool parameter: its name, human description, and schema type. Source: agents/agents-tools/.../tools/ToolDescriptor.kt.
struct ToolDescriptor
A tool's schema as the LLM is shown it (Koog ToolDescriptor): the name it is called by, a description, and the required / optional parameter lists. Source: agents/agents-tools/.../tools/ToolDescriptor.kt.
fn ToolParameterType::to_json_schema(self : ToolParameterType) -> Json
This parameter type as a JSON Schema fragment — what a tool/function definition advertises to the model, and what a structured-output request constrains the reply to. Koog derives the schema from the Kotlin type via kotlinx.serialization; with no reflection here it is rendered from the explicit ToolParameterType.
pub(open) trait ToolA callable tool. Koog's Tool<TArgs, TResult> derives its schema from the argument type via kotlinx.serialization + a TypeToken; MoonBit has no reflection, so a tool states its descriptor() explicitly and execute_raw decodes the JSON arguments, runs, and encodes the result to the string the model is shown — Koog's decodeArgs + execute + encodeResultToString collapsed to the SimpleTool<TArgs> : String shape. Source: agents/agents-tools/.../tools/{ToolBase,Tool,SimpleTool}.kt.
struct ToolRegistry
A set of tools addressable by name. Koog ToolRegistry. Source: agents/agents-tools/.../tools/ToolRegistry.kt.
fn ToolRegistry::new() -> ToolRegistry
An empty registry (Koog ToolRegistry.EMPTY).
fn ToolRegistry::add(self : ToolRegistry, tool : &Tool) -> ToolRegistry
Register a tool and return the registry, so registration chains (MoonBit has no receiver-lambda DSL for Koog's ToolRegistry { tool(...) }).
fn ToolRegistry::get_tool(self : ToolRegistry, name : String) -> &Tool?
The tool named name, or None (Koog getToolOrNull).
fn ToolRegistry::descriptors(self : ToolRegistry) -> Array[ToolDescriptor]
Every registered tool's descriptor — what a request advertises to the model.
struct ExitTool
End the agent run and return result as the final answer (Koog ExitTool).
fn ExitTool::new() -> ExitTool
The exit tool.
impl Tool for ExitTool with fn descriptor(_self)
impl Tool for ExitTool with fn execute_raw(_self, args)
struct SayToUser
Show a message to the user through the configured sink (Koog SayToUser).
fn SayToUser::new(sink : (String) -> Unit) -> SayToUser
A say-to-user tool that writes messages to sink.
impl Tool for SayToUser with fn descriptor(_self)
impl Tool for SayToUser with fn execute_raw(self, args)
struct AskUser
Ask the user a question and return their reply from the configured responder (Koog AskUser).
fn AskUser::new(responder : (String) -> String) -> AskUser
An ask-user tool that reads replies from responder.
impl Tool for AskUser with fn descriptor(_self)
impl Tool for AskUser with fn execute_raw(self, args)
pub(open) trait FileSystemThe filesystem a file tool reads and writes through (Koog FileSystemProvider).
struct MemFileSystem
An in-memory filesystem: a map of path to contents; list returns the paths under a directory prefix.
fn MemFileSystem::new() -> MemFileSystem
An empty in-memory filesystem.
impl FileSystem for MemFileSystem with fn read(self, path)
impl FileSystem for MemFileSystem with fn write(self, path, content)
impl FileSystem for MemFileSystem with fn list(self, path)
struct ReadFileTool
Read a file's contents (Koog ReadFileTool).
fn ReadFileTool::new(fs : &FileSystem) -> ReadFileTool
A read-file tool over fs.
impl Tool for ReadFileTool with fn descriptor(_self)
impl Tool for ReadFileTool with fn execute_raw(self, args)
struct WriteFileTool
Write contents to a file (Koog WriteFileTool).
fn WriteFileTool::new(fs : &FileSystem) -> WriteFileTool
A write-file tool over fs.
impl Tool for WriteFileTool with fn descriptor(_self)
impl Tool for WriteFileTool with fn execute_raw(self, args)
struct ListDirectoryTool
List the files under a directory (Koog ListDirectoryTool).
fn ListDirectoryTool::new(fs : &FileSystem) -> ListDirectoryTool
A list-directory tool over fs.
impl Tool for ListDirectoryTool with fn descriptor(_self)
impl Tool for ListDirectoryTool with fn execute_raw(self, args)
pub(open) trait ShellExecutorRuns a shell command line and returns its output (Koog ShellCommandExecutor).
struct ExecuteShellCommandTool
Run a shell command through the configured executor (Koog ExecuteShellCommandTool).
fn ExecuteShellCommandTool::new( executor : &ShellExecutor) -> ExecuteShellCommandTool
A shell-command tool over executor.
impl Tool for ExecuteShellCommandTool with fn descriptor(_self)
impl Tool for ExecuteShellCommandTool with fn execute_raw(self, args)
struct RegexSearchTool
Search the files under a path for pattern, listing those whose contents match (Koog RegexSearchTool).
fn RegexSearchTool::new(fs : &FileSystem) -> RegexSearchTool
A regex-search tool over fs.
impl Tool for RegexSearchTool with fn descriptor(_self)
impl Tool for RegexSearchTool with fn execute_raw(self, args)
§The agent
AIAgent and the strategy graph it walks. run is not a special-cased loop, it is run_strategy wired with single_run_strategy. A RunHandle stops a run between nodes, so a tool call in progress always finishes. EventHandler observes every step.
suberror AgentErrorWhat ends a run other than an answer: AgentError when the loop runs longer than max_iterations without the model producing a final text answer, AgentStopped when the run was asked to stop through its [RunHandle], carrying the text it had reached by then.
struct RunHandle
A handle for stopping a run from outside it. Koog cancels the agent's coroutine, which can land in the middle of a tool call; a graph walk can stop more politely than that, so a run holding one of these finishes the node it is in and stops at the next boundary. Hand the same handle to run or run_strategy and call stop from anywhere — a supervisor, a signal handler, a deadline.
fn RunHandle::new() -> RunHandle
A handle that has not been asked to stop.
fn RunHandle::stop(self : RunHandle) -> Unit
Ask the run to stop at its next node boundary. Calling this more than once, or after the run has finished, does nothing further.
fn RunHandle::stopping(self : RunHandle) -> Bool
Whether a stop has been requested.
struct AIAgent
A single-run agent — Koog's AIAgent as built by its ergonomic factory over the default singleRunStrategy. It pairs an LLM executor + model with a tool registry and an optional system prompt, and runs the tool-calling loop. params is what Koog's AIAgentConfig carries inside its whole Prompt: every request a run makes starts from it, so temperature, tool choice, token cap and the rest reach the provider. Source: agents/agents-core/.../agent/{AIAgent,AIAgentFactory,AIAgentConfig}.kt.
fn AIAgent::new( executor : &LLMClient, model~ : @llm.LLModel, tool_registry? : @tools.ToolRegistry = @tools.ToolRegistry::new(), system_prompt? : String? = None, params? : @prompt.LLMParams = @prompt.LLMParams::default(), max_iterations? : Int = 50, events? : EventHandler = EventHandler::new()) -> AIAgent
Build an agent. params defaults to the provider's own defaults (Koog's empty LLMParams); max_iterations to Koog's 50; events to a no-op handler (install one to observe the run).
async fn AIAgent::run( self : AIAgent, input : String, stop? : RunHandle, checkpoints? : Checkpointer, resume_from? : AgentCheckpoint) -> String
Run the agent on input, returning the final assistant text. Koog's default singleRunStrategy: request a completion; return it if it is plain text; otherwise run every requested tool, feed the results back, and request again, bounded by max_iterations. This delegates to run_strategy with single_run_strategy — the loop is not special-cased, it is one wiring of the strategy graph (see strategy.mbt), the way Koog builds singleRunStrategy from the same graph DSL. Source: agents/agents-core/.../agent/AIAgentSimpleStrategies.kt (singleRunStrategy).
enum NodeValue
The value passed between strategy nodes: the text that enters at the start and leaves at the finish, an LLM assistant reply, the JSON a structured request parsed, a moderation verdict, or a bare token from a node whose effect is on the conversation (tools executed) rather than on a carried value.
fn NodeValue::text(self : NodeValue) -> String
The text a NodeValue carries: the raw text, an assistant reply's text, the JSON re-serialized, a moderation verdict as harmful / safe, or empty.
fn NodeValue::to_json(self : NodeValue) -> Json
The value as Json, tagged by variant, so a checkpoint can carry what was in flight between two nodes.
fn NodeValue::from_json(json : Json) -> NodeValue raise AgentError
Read back a value written by to_json. Raises AgentError on a tag or payload that does not belong to a NodeValue — a checkpoint that cannot be decoded cannot be resumed from, and saying so beats resuming at the right node with the wrong value.
enum NodeKind
A standard node's behaviour (Koog's nodeStart / nodeFinish / nodeLLMRequest / nodeExecuteTool / nodeLLMSendToolResult). NodeExecuteTools runs every tool call in the reply (Koog's multiple-tool variant), matching the conversation the loop builds.
enum EdgeCondition
When an edge fires, tested against the source node's output. Always is an unconditional edge; OnAssistantMessage fires on a plain-text reply (no tool calls); OnToolCalls fires on a reply that requests tools; OnPredicate fires on any test of the value at all. Koog's onCondition / onAssistantMessage / onToolCall.
struct StrategyEdge
A directed edge from -> to that fires when condition holds.
struct AIAgentStrategy
A strategy graph: named nodes, edges between them, and the start / finish node names. max_steps bounds node visits, a backstop against a cyclic graph that never reaches finish (the per-agent max_iterations bounds LLM calls).
let start_node : String = "__start__"
The canonical start / finish node names.
let finish_node : String = "__finish__"
fn AIAgentStrategy::new( name : String, max_steps? : Int = 1000) -> AIAgentStrategy
A strategy seeded with the start and finish nodes, ready to have nodes and edges added. max_steps defaults to a generous backstop.
fn AIAgentStrategy::node( self : AIAgentStrategy, name : String, kind : NodeKind) -> AIAgentStrategy
Add a named node, returning the strategy so calls chain.
fn AIAgentStrategy::custom_node( self : AIAgentStrategy, name : String, handler : async (NodeSession, NodeValue) -> NodeValue) -> AIAgentStrategy
Add a custom node name whose behaviour is handler — an arbitrary step run against a NodeSession (Koog's node<In, Out> { ... }). Returns the strategy so calls chain.
fn AIAgentStrategy::subgraph( self : AIAgentStrategy, name : String, strategy : AIAgentStrategy) -> AIAgentStrategy
Add node name that runs the whole of strategy and carries its finish value on (Koog's subgraph). Returns the strategy so calls chain.
fn AIAgentStrategy::subgraph_retry( self : AIAgentStrategy, name : String, strategy : AIAgentStrategy, until~ : (NodeValue) -> Bool, max_retries? : Int = 2) -> AIAgentStrategy
Add node name that runs strategy and re-runs it while until rejects the result, at most max_retries extra times (Koog's SubgraphWithRetry). Returns the strategy so calls chain.
fn AIAgentStrategy::parallel( self : AIAgentStrategy, name : String, nodes : Array[String], merge~ : (Array[NodeValue]) -> NodeValue) -> AIAgentStrategy
Add node name that runs every node in nodes at once on the same input and hands their results, in that order, to merge (Koog's parallel). Returns the strategy so calls chain.
fn AIAgentStrategy::edge( self : AIAgentStrategy, from : String, to : String, condition? : EdgeCondition = Always, transform? : ((NodeValue) -> NodeValue)? = None) -> AIAgentStrategy
Add an edge from -> to firing on condition (unconditional by default), returning the strategy so calls chain. transform rewrites the value the next node sees.
fn single_run_strategy(max_steps? : Int = 1000) -> AIAgentStrategy
Koog's singleRunStrategy expressed as a graph: request the LLM; on a plain-text reply finish, on a tool-call reply execute the tools, feed the results back, and request again — looping until the model answers in text.
fn chat_agent_strategy(max_steps? : Int = 1000) -> AIAgentStrategy
Koog's chatAgentStrategy expressed as a graph: request the LLM; a tool call is executed, but a plain-text reply is nudged ("call a tool instead of chatting") and the LLM re-requested until it calls a tool; the loop finishes when the model calls the exit tool (__exit__), whose edge carries "Chat finished" as the result.
fn react_strategy( reasoning_interval? : Int = 1, reasoning_prompt? : String = "Please give your thoughts about the task and plan the next steps.", max_steps? : Int = 1000) -> AIAgentStrategy
Koog's reActStrategy: alternate reasoning and action. Each round reasons (a tools-off request seeded with reasoning_prompt), then acts (a request with tools); a tool call is executed and, every reasoning_interval rounds, the results are reasoned over before the next action; a plain-text reply finishes. Built on custom nodes carrying a reasoning-step counter in the session's per-run store.
struct NodeSession
The session a custom node runs against (Koog's AIAgentLLMWriteSession receiver): the request/append/storage operations a node closure needs, without exposing the whole context. This is the MoonBit stand-in for Kotlin's receiver-lambda node DSL.
fn NodeSession::append_user(self : NodeSession, text : String) -> Unit
Append a user message to the conversation.
fn NodeSession::append( self : NodeSession, message : @prompt.Message) -> Unit
Append a ready message to the conversation.
async fn NodeSession::request_llm(self : NodeSession) -> @prompt.Message
Request the model with the advertised tools (Koog requestLLM).
async fn NodeSession::request_llm_no_tools( self : NodeSession) -> @prompt.Message
Request the model with no tools — a reasoning step (Koog requestLLMWithoutTools).
fn NodeSession::storage(self : NodeSession) -> AgentStorage
The run's AIAgentStorage — what a node reaches for when it wants the whole store rather than one entry (contains, remove, a snapshot).
fn[T : @json.FromJson] NodeSession::get( self : NodeSession, key : String) -> T?
Read the value stored under key at the type the call site asks for; None when the key is unset or its Json does not decode to that type.
fn[T : ToJson] NodeSession::set( self : NodeSession, key : String, value : T) -> Unit
Store any ToJson value under key, replacing what was there.
fn NodeSession::tool_names(self : NodeSession) -> Array[String]
The names of the tools advertised to the model.
async fn AIAgent::run_strategy( self : AIAgent, strategy : AIAgentStrategy, input : String, stop? : RunHandle, checkpoints? : Checkpointer, resume_from? : AgentCheckpoint) -> String
Run strategy on input, returning the finish node's text. Seeds the prompt with the agent's params and system message, then walks the graph. LLM requests are bounded by the agent's max_iterations (Koog's iteration cap) across the whole run, nested subgraphs and parallel branches included; node visits by each strategy's max_steps. With checkpoints, every top-level node boundary is snapshotted into the given store before the node runs. Passing one of those snapshots back as resume_from replays its conversation, storage and spent-iteration count and re-enters the walk at the node it was taken before, so a run picks up where it stopped instead of starting over; input is then unused, the value in flight coming from the checkpoint.
struct EventHandler
Lifecycle hooks over an agent run (← Koog's agents-features-event-handler EventHandlerConfig): observe the agent starting and completing, each LLM call, each tool call, and each strategy node as it runs. The transcribed core of Koog's hook set — enough for logging, tracing, and token accounting to sit outside the agent loop. Registering a handler *chains* it after any already registered for that hook, so several observers all fire (Koog composes the previous handler with the new one). Hooks are synchronous; an async observer is a later refinement, as Koog's suspend hooks are.
fn EventHandler::new() -> EventHandler
An event handler with every hook a no-op — the default an agent carries when no observer is installed.
fn EventHandler::on_agent_starting( self : EventHandler, handler : (String) -> Unit) -> EventHandler
Observe the agent starting, on its input. Chains after any prior handler.
fn EventHandler::on_agent_completed( self : EventHandler, handler : (String) -> Unit) -> EventHandler
Observe the agent completing, with its final text. Chains.
fn EventHandler::on_llm_call_starting( self : EventHandler, handler : (@prompt.Prompt) -> Unit) -> EventHandler
Observe each LLM request just before it is sent, with the prompt. Chains.
fn EventHandler::on_llm_call_completed( self : EventHandler, handler : (@prompt.Message) -> Unit) -> EventHandler
Observe each LLM reply, with the assistant message. Chains.
fn EventHandler::on_tool_call_starting( self : EventHandler, handler : (String, Json) -> Unit) -> EventHandler
Observe each tool call before it runs, with the tool name and JSON arguments. Chains.
fn EventHandler::on_tool_call_completed( self : EventHandler, handler : (String, String) -> Unit) -> EventHandler
Observe each tool call after it runs, with the tool name and its result string. Chains.
fn EventHandler::on_node_execution_starting( self : EventHandler, handler : (String) -> Unit) -> EventHandler
Observe each strategy node before it runs, by name. Chains.
fn EventHandler::on_node_execution_completed( self : EventHandler, handler : (String) -> Unit) -> EventHandler
Observe each strategy node after it runs, by name. Chains.
pub(open) trait LLMClientThe LLM client contract (Koog LLMClientAPI, collapsed for the MVP with the single-LLM PromptExecutor — a single-provider executor is a one-line delegate to its client). execute sends a prompt with the tool descriptors the model may call and returns the assistant reply; any tool calls come back inside the reply's parts as ToolCalls. moderate checks a prompt against the provider's safety categories; its default reports nothing harmful, and a client that supports moderation overrides it. execute_multiple returns one reply per requested choice (Koog executeMultipleChoices, the count being prompt.params.number_of_choices); a provider without multi-choice returns a single-element list. Streaming is deferred to the async-stream layer. Source: prompt/prompt-executor/prompt-executor-clients/.../LLMClientAPI.kt.
struct MockClient
A deterministic in-memory client for tests: it replays a scripted list of assistant replies, one per execute call, ignoring the prompt. This is what lets the agent loop be tested without a network or a real model — the loop's control flow is exercised by scripting "reply with a tool call", then "reply with the final text".
fn MockClient::new( scripted : Array[@prompt.Message], provider? : @llm.LLMProvider = @llm.openai) -> MockClient
A mock that will hand back scripted replies in order.
impl LLMClient for MockClient with fn execute(self, prompt~, model~, tools~)
impl LLMClient for MockClient with fn provider(self)
impl LLMClient for MockClient with fn moderate(self, prompt~, model~)
impl LLMClient for MockClient with fn execute_multiple( self, prompt~, model~, tools~)
The scripted equivalent of a multi-choice request: hand back the next prompt.params.number_of_choices scripted replies, one per candidate, the way a provider returns one completion per requested choice.
struct AgentResponse
An HTTP response: a status code and a JSON body.
struct AgentEndpoint
An HTTP endpoint that runs agent for each request (Koog RoutingContext.aiAgent).
fn AgentEndpoint::new(agent : AIAgent) -> AgentEndpoint
An endpoint serving agent.
async fn AgentEndpoint::handle( self : AgentEndpoint, body : String) -> AgentResponse
Handle a request body {"message": "..."}: run the agent and answer {"output": "..."} with status 200, or 400 when the body is not a valid request.
async fn AgentEndpoint::handle_sse( self : AgentEndpoint, body : String) -> String
Handle a request and stream the answer as one Server-Sent Event data: frame (Koog's sse helper), or an error event when the body is invalid.
§Strategies built on the graph
Planning, self-criticism, GOAP, node choice, multi-agent delegation and schema-constrained output - each one a wiring of the same graph rather than a loop of its own.
struct PlanStep
One step of a plan: what to do, and whether it is already done (Koog PlanStep).
struct SimplePlan
A plan: the overall goal and the ordered steps that reach it (Koog SimplePlan).
enum PlanAssessment
A verdict on the current plan before a step runs (Koog SimplePlanAssessment): keep going, throw it away and replan with a reason, or there is no plan yet.
struct LLMPlanner
A planner backed by client / model. With with_critic set it re-judges the plan with the model before each step (Koog SimpleLLMWithCriticPlanner); otherwise it keeps any existing plan (Koog SimpleLLMPlanner).
fn LLMPlanner::new(client : &LLMClient, model : @llm.LLModel) -> LLMPlanner
A planner over client / model that keeps its plan once built.
fn LLMPlanner::with_critic(self : LLMPlanner) -> LLMPlanner
The same planner with the LLM critic enabled (Koog Planners.llmBasedWithCritic).
async fn LLMPlanner::assess_plan( self : LLMPlanner, state : String, plan : SimplePlan?) -> PlanAssessment
Judge the current plan. With no plan there is nothing to judge; without the critic the plan is always kept; with the critic the model replies CONTINUE to keep it or REPLAN: <reason> to discard it.
async fn LLMPlanner::build_plan( self : LLMPlanner, state : String, plan : SimplePlan?) -> SimplePlan
Produce the plan to execute next: keep the current one if the assessment says so, otherwise ask the model for a fresh plan (feeding it the failed plan and the reason when replanning).
async fn LLMPlanner::execute_step( self : LLMPlanner, state : String, plan : SimplePlan) -> String
Execute the first not-yet-done step of plan against state, mark it done, and return the model's output as the new state. When every step is done the plan is complete.
fn LLMPlanner::is_plan_completed( self : LLMPlanner, plan : SimplePlan) -> Bool
Whether every step of plan is done (Koog isPlanCompleted).
async fn LLMPlanner::run( self : LLMPlanner, input : String, max_steps? : Int = 32) -> String
Run the planner end to end (Koog AIAgentPlanner.execute): build a plan, execute its steps one by one re-judging before each, and return the final state. max_steps bounds the loop the way Koog's maxAgentIterations does.
struct CriticVerdict
A critic's verdict on a solution: whether it passed, and any feedback (Koog CriticResult).
struct LLMCritic
An LLM critic that judges solutions with client / model.
fn LLMCritic::new(client : &LLMClient, model : @llm.LLModel) -> LLMCritic
A critic backed by client / model.
async fn LLMCritic::judge( self : LLMCritic, task : String, solution : String) -> CriticVerdict
Ask the model whether solution correctly solves task. A reply beginning CORRECT passes; otherwise it fails, and the text after the first colon is the feedback.
struct GoapAction[S]
An action: its name, when it applies, the state it produces, and its cost.
struct GoapGoal[S]
A goal: whether a state satisfies it, and a heuristic estimate of the cost still to go.
fn[S : Eq + Hash] goap_plan( actions : Array[GoapAction[S]], initial : S, goal : GoapGoal[S]) -> Array[String]?
Plan the least-cost action-name sequence from initial to a state satisfying goal with A* over the state space, or None when the goal is unreachable.
pub(open) trait ChoiceSelectionStrategyA strategy for choosing one reply among several candidates for a prompt.
struct FirstChoice
Take the first candidate (Koog ChoiceSelectionStrategy.Default).
fn FirstChoice::new() -> FirstChoice
The first-choice selector.
impl ChoiceSelectionStrategy for FirstChoice with fn choose( _self, _prompt, choices)
struct LLMChoiceSelector
Ask a model to judge which candidate is best and return it (Koog's LLM-backed choice selection).
fn LLMChoiceSelector::new( client : &LLMClient, model : @llm.LLModel) -> LLMChoiceSelector
A selector that judges with client / model.
impl ChoiceSelectionStrategy for LLMChoiceSelector with fn choose( self, _prompt, choices)
struct MultiLLMClient
One LLMClient over several providers (← Koog's MultiLLMPromptExecutor): register a client per provider, and every request routes to the client whose provider matches the request's model.provider. An optional fallback client serves any provider that was not registered. Because MoonBit's LLMClient.execute does not raise, a request for a provider with neither a client nor a fallback gets a plain assistant message naming the miss, rather than a crash — an honest, visible degradation of Koog's IllegalArgumentException.
fn MultiLLMClient::new( default_provider? : @llm.LLMProvider = @llm.openai) -> MultiLLMClient
An empty router. default_provider is what the router reports as its own provider() (Koog executors are provider-agnostic; a value is still required).
fn MultiLLMClient::register( self : MultiLLMClient, provider : @llm.LLMProvider, client : &LLMClient) -> MultiLLMClient
Register client for provider, returning the router so registrations chain.
fn MultiLLMClient::with_fallback( self : MultiLLMClient, client : &LLMClient) -> MultiLLMClient
Set the fallback client used for any provider without its own registration.
impl LLMClient for MultiLLMClient with fn execute( self, prompt~, model~, tools~)
impl LLMClient for MultiLLMClient with fn provider(self)
impl LLMClient for MultiLLMClient with fn moderate(self, prompt~, model~)
impl LLMClient for MultiLLMClient with fn execute_multiple( self, prompt~, model~, tools~)
struct StructuredSchema[T]
A structured-response request: the schema the reply must match and the parser that turns its JSON into a T.
struct StructuredResponse[T]
A structured request's result: the parsed value and the raw model text it came from.
async fn[T] AIAgent::request_structured( self : AIAgent, input : String, schema : StructuredSchema[T], max_fixes? : Int = 2) -> StructuredResponse[T]
Request a structured response to input, retrying up to max_fixes times when the reply does not parse. Asks through the provider's own structured-output format when the model declares a JSON-schema capability, and states the schema in the prompt as well, so a provider that ignores response_format still has the shape in front of it. On each malformed reply it appends the bad output and a fixing instruction and asks again — Koog's StructureFixingParser. Raises AgentError if no reply parses within the budget.
§Around the run
Retry, response caching, moderation, history compression, checkpointing and the storage behind them.
enum RetryPattern
What marks an error as worth retrying (Koog RetryablePattern): a substring of the error's described message, matched case-insensitively, or an HTTP status code appearing in it.
fn RetryPattern::matches(self : RetryPattern, message : String) -> Bool
Whether message matches this pattern.
struct RetryConfig
How a retry is paced (Koog RetryConfig): how many attempts in total, the wait before the first retry, the ceiling that wait grows to, the factor it grows by, and how far the wait is randomly spread either side of its nominal value to keep concurrent clients from retrying in lockstep. patterns is what makes an error retryable at all.
fn RetryConfig::default() -> RetryConfig
Koog's RetryConfig.DEFAULT: three attempts, 1s growing by 2× to a 30s ceiling, 10% jitter, retrying the transient provider failures — rate limits, 5xx, timeouts, dropped connections.
fn RetryConfig::disabled() -> RetryConfig
Koog's RetryConfig.DISABLED: one attempt, so nothing is ever retried.
fn RetryConfig::matches(self : RetryConfig, message : String) -> Bool
Whether any configured pattern claims message.
fn RetryConfig::delay_ms(self : RetryConfig, attempt : Int) -> Int
The nominal wait before retry number attempt (1 for the first retry): the initial delay grown by backoff_multiplier once per earlier retry, capped at max_delay_ms. Jitter is applied on top of this by the client, which owns the randomness.
fn default_describe(error : Error) -> String
What a bare Error says about itself: its constructor's qualified name, and nothing of the payload. The fallback describer, and the reason a caller wants to replace it.
struct RetryingClient
A client that retries execute on a retryable failure, backing off between attempts.
fn RetryingClient::new( inner : &LLMClient, config? : RetryConfig = RetryConfig::default(), describe? : (Error) -> String = default_describe, retryable? : ((Error) -> Bool)? = None, wait? : async (Int) -> Unit = @async.sleep, seed? : Bytes? = None) -> RetryingClient
Wrap inner. config paces the retries and holds the patterns; describe turns a caught error into the message those patterns are matched against — the default sees only the error's type name, so pass the describer for the client's own error type (@client.describe_llm_error for the OpenAI-compatible and Anthropic clients) or nothing will look retryable. retryable replaces that classification outright. wait is the sleep — the default is real time, a test passes a recorder. seed seeds the jitter: MoonBit has no ambient entropy, so without one every client jitters the same sequence.
impl LLMClient for RetryingClient with fn execute( self, prompt~, model~, tools~)
impl LLMClient for RetryingClient with fn provider(self)
impl LLMClient for RetryingClient with fn moderate(self, prompt~, model~)
impl LLMClient for RetryingClient with fn execute_multiple( self, prompt~, model~, tools~)
struct CachingClient
A client that caches execute replies by prompt + model.
fn CachingClient::new(inner : &LLMClient) -> CachingClient
Wrap inner with an in-memory reply cache.
fn CachingClient::size(self : CachingClient) -> Int
The number of distinct prompts currently cached.
impl LLMClient for CachingClient with fn execute( self, prompt~, model~, tools~)
impl LLMClient for CachingClient with fn provider(self)
impl LLMClient for CachingClient with fn moderate(self, prompt~, model~)
impl LLMClient for CachingClient with fn execute_multiple( self, prompt~, model~, tools~)
struct ModerationCategoryResult
One safety category's verdict (Koog ModerationCategoryResult): whether the category was detected in the content and, when the provider gives one, its confidence score.
struct ModerationResult
A moderation verdict (Koog ModerationResult): whether the content is harmful overall and the per-category detections a provider's moderation endpoint returned.
fn ModerationResult::safe() -> ModerationResult
A verdict that flags nothing — what a client without moderation support returns.
fn ModerationResult::is_category_detected( self : ModerationResult, category : String) -> Bool
Whether category was detected in the moderated content.
enum HistoryCompression
Which part of the history to compress (Koog's default strategies).
struct HistoryCompressor
Compresses a conversation with client / model.
fn HistoryCompressor::new( client : &LLMClient, model : @llm.LLModel) -> HistoryCompressor
A compressor backed by client / model.
async fn HistoryCompressor::compress( self : HistoryCompressor, messages : Array[@prompt.Message], strategy : HistoryCompression) -> Array[@prompt.Message]
Compress messages per strategy, returning the new message list: the summary first, then any kept messages. A list with nothing to summarise is returned unchanged.
using @persistence
The checkpoint record and its in-memory store, re-exported under @agent.
struct Checkpointer
Where a run's node-boundary snapshots go: the store, the session id they are filed under, and the clock that stamps them. MoonBit has no ambient clock, so a caller that cares about wall time supplies one; without it a checkpoint is stamped with its sequence number, which orders a session's checkpoints correctly and keeps tests deterministic.
fn Checkpointer::new( store : &@persistence.PersistenceStorageProvider, session~ : String, clock? : (() -> Int64)? = None) -> Checkpointer
Snapshot every node boundary of a run into store under session.
struct AgentStorage
A per-agent key-value store of Json-serialized values.
fn AgentStorage::new() -> AgentStorage
A fresh empty store.
fn[T : ToJson] AgentStorage::set( self : AgentStorage, key : String, value : T) -> Unit
Serialize value and store it under key, replacing any existing value.
fn[T : @json.FromJson] AgentStorage::get( self : AgentStorage, key : String) -> T?
The value stored under key, deserialized to T, or None if the key is absent or its stored Json does not decode to T.
fn AgentStorage::contains(self : AgentStorage, key : String) -> Bool
Whether a value is stored under key.
fn AgentStorage::remove(self : AgentStorage, key : String) -> Bool
Remove key; returns whether it was present.
fn AgentStorage::clear(self : AgentStorage) -> Unit
Remove every entry.
fn AgentStorage::size(self : AgentStorage) -> Int
The number of stored entries.
fn AgentStorage::snapshot(self : AgentStorage) -> Json
A Json snapshot of the whole store — every entry as a field of a Json object (Koog's toSerializedMap). This is what a checkpoint persists.
fn AgentStorage::restore(self : AgentStorage, snapshot : Json) -> Unit
Replace the store's contents from a snapshot Json object, for restoring from a checkpoint.
§LLM clients
The OpenAI and Anthropic executors, and the embedding client. Native-only: they reach the network.
struct OpenAiCompatibleClient
An OpenAI-compatible LLM client (Koog OpenAILLMClient and its provider siblings). It implements moonkoog's LLMClient by mapping Koog's prompt/message/tool model onto moonllm's request/response types and back; moonllm carries the actual HTTPS transport. One client talks to any OpenAI-compatible endpoint by its base_url. Source: prompt/prompt-executor/prompt-executor-clients/prompt-executor-openai-client/.../OpenAILLMClient.kt.
fn OpenAiCompatibleClient::new( api_key~ : String, base_url~ : String, provider~ : @llm.LLMProvider, timeout_ms? : Int = 60000) -> OpenAiCompatibleClient
Build a client for base_url, authenticating with a bearer api_key.
impl @agent.LLMClient for OpenAiCompatibleClient with fn execute( self, prompt~, model~, tools~)
impl @agent.LLMClient for OpenAiCompatibleClient with fn execute_streaming( self, prompt~, model~, tools~, on_chunk~)
Stream the OpenAI-compatible chat completion (Koog OpenAILLMClient.executeStreaming): send with stream: true, invoke on_chunk for each text_delta off the SSE feed, and assemble the full reply (text plus any streamed tool calls) once the stream ends.
impl @agent.LLMClient for OpenAiCompatibleClient with fn provider(self)
impl @agent.LLMClient for OpenAiCompatibleClient with fn moderate( self, prompt~, model~)
Moderate the prompt through the OpenAI-compatible /moderations endpoint (Koog OpenAILLMClient.moderate): the prompt's text is sent to the moderation model and the returned per-category flags and confidence scores are mapped back to a Koog ModerationResult.
impl @agent.LLMClient for OpenAiCompatibleClient with fn execute_multiple( self, prompt~, model~, tools~)
Request number_of_choices completions (Koog executeMultipleChoices) and map each returned choice to a Koog message. The count comes from the prompt's params (default 1); OpenAI-compatible endpoints carry it as the n field.
fn to_anthropic_request( prompt : @prompt.Prompt, model : @llm.LLModel, tools : Array[@tools.ToolDescriptor]) -> Json
Build an Anthropic Messages API request from a Koog prompt, model, and tools. System messages are lifted to the top-level system field; max_tokens (required by Anthropic) comes from the params, then the model's output limit, then a default of 4096.
fn from_anthropic_response(response : Json) -> @prompt.Message
Parse an Anthropic Messages API response into a Koog assistant message: each text content block becomes a Text part, each tool_use block a ToolCall (its input the arguments), and stop_reason the finish reason.
struct AnthropicClient
An Anthropic Messages API client (Koog AnthropicLLMClient) — the second wire format alongside the OpenAI-compatible client. It implements moonkoog's LLMClient by mapping Koog's prompt/message/tool model onto the Anthropic request/response JSON (to_anthropic_request / from_anthropic_response) and POSTing to /messages; moonllm carries the HTTPS transport, configured for Anthropic's x-api-key auth and required anthropic-version header. Source: prompt/.../clients/anthropic/AnthropicLLMClient.kt.
fn AnthropicClient::new( api_key~ : String, base_url? : String = "https://api.anthropic.com/v1", version? : String = "2023-06-01", timeout_ms? : Int = 60000) -> AnthropicClient
Build a client for the Anthropic Messages API, authenticating with api_key via x-api-key and sending the anthropic-version. base_url defaults to Anthropic's public API; point it at a compatible gateway to override.
impl @agent.LLMClient for AnthropicClient with fn execute( self, prompt~, model~, tools~)
impl @agent.LLMClient for AnthropicClient with fn provider(self)
impl @agent.LLMClient for AnthropicClient with fn moderate( self, prompt~, model~)
Anthropic exposes no standalone moderation endpoint (unlike OpenAI's /moderations), so this honours the moderation contract by reporting nothing harmful; callers needing real moderation route it through a provider that offers it.
impl @agent.LLMClient for AnthropicClient with fn execute_multiple( self, prompt~, model~, tools~)
The Anthropic Messages API returns a single completion (there is no n), so multiple choices collapse to a single-element list.
struct LLMEmbedder
An embedder that calls an OpenAI-compatible /embeddings endpoint. model is the embedding model id (e.g. text-embedding-3-small); moonllm carries the HTTPS transport.
fn LLMEmbedder::new( api_key~ : String, base_url~ : String, model~ : String, timeout_ms? : Int = 60000) -> LLMEmbedder
Build an embedder for base_url, authenticating with a bearer api_key and requesting model.
impl @embeddings.Embedder for LLMEmbedder with fn embed(self, text)
impl @embeddings.Embedder for LLMEmbedder with fn diff( self, embedding1, embedding2)
§Embeddings and retrieval
Vectors and their similarity, the embedder contract, and the vector store a retrieval step queries.
suberror VectorErrorA dimension mismatch in an operation that requires two vectors of equal length.
struct Vector
A vector of floating-point values — the embedding of a piece of text.
fn Vector::dimension(self : Vector) -> Int
The number of components in the vector.
fn Vector::is_null(self : Vector) -> Bool
Whether every component is 0.0.
fn Vector::magnitude(self : Vector) -> Double
The Euclidean norm — the square root of the sum of squared components.
fn Vector::dot_product(self : Vector, other : Vector) -> Double
The dot product with other — the sum of products of corresponding components (over the shorter length when the dimensions differ, matching Koog's zip).
fn Vector::cosine_similarity(self : Vector, other : Vector) -> Double raise
The cosine similarity with other, in [-1, 1]: 1 for identical directions, 0 for orthogonal (or either vector null), -1 for opposite. Raises VectorError on a dimension mismatch.
fn Vector::euclidean_distance( self : Vector, other : Vector) -> Double raise
The Euclidean distance to other — 0 for identical vectors. Raises VectorError on a dimension mismatch.
pub(open) trait EmbedderTurns text into an embedding vector and scores the difference between two embeddings.
struct MockEmbedder
A deterministic embedder for tests and offline use: it maps text to a fixed 4-dimensional vector by bucketing each code unit, so equal text yields equal vectors and shared characters pull two texts' vectors together — no network. diff is the cosine distance (1 - cosine similarity).
fn MockEmbedder::new(dimension? : Int = 4) -> MockEmbedder
A fresh deterministic embedder producing dimension-component vectors (default 4).
impl Embedder for MockEmbedder with fn embed(self, text)
impl Embedder for MockEmbedder with fn diff(self, embedding1, embedding2)
enum ScoreMetric
The metric a similarity score was computed with (Koog ScoreMetric).
struct Score
A similarity score and the metric it was computed with (Koog Score).
struct SearchResult[Doc]
A search hit: a stored document and the score it earned against the query (Koog SearchResult).
struct VectorStore[Doc]
An in-memory store of documents keyed by a generated id, each paired with its embedding vector (Koog InMemoryVectorStorageBackend). Ids are sequential (doc-0, doc-1, …) rather than random UUIDs, so the store is deterministic.
fn[Doc] VectorStore::new() -> VectorStore[Doc]
A fresh empty store.
fn[Doc] VectorStore::store( self : VectorStore[Doc], document : Doc, vector : @embeddings.Vector) -> String
Store document with its vector, returning the id assigned to it.
fn[Doc] VectorStore::get(self : VectorStore[Doc], id : String) -> Doc?
The document stored under id, or None.
fn[Doc] VectorStore::delete(self : VectorStore[Doc], id : String) -> Bool
Remove the document under id; returns whether it was present.
fn[Doc] VectorStore::size(self : VectorStore[Doc]) -> Int
The number of stored documents.
fn[Doc] VectorStore::pairs( self : VectorStore[Doc]) -> Array[(Doc, @embeddings.Vector)]
Every stored (document, vector) pair — the input a similarity search ranks over.
fn[Doc] rank_by_similarity( query : @embeddings.Vector, documents : Array[(Doc, @embeddings.Vector)], limit? : Int = 10, offset? : Int = 0, min_score? : Double = 0.0) -> Array[SearchResult[Doc]] raise
Rank documents (each a document paired with its embedding) against query by cosine similarity (Koog EmbeddingStorage.search): score each, keep those at or above min_score, sort by score descending, then skip offset and keep at most limit. Raises @embeddings.VectorError on a dimension mismatch.
struct EmbeddingStorage[Doc]
A document store that embeds documents on insertion and queries on search (Koog EmbeddingStorage): to_text extracts the text to embed from a document, the Embedder turns text into vectors, and the VectorStore holds them for cosine-similarity retrieval.
fn[Doc] EmbeddingStorage::new( embedder : &@embeddings.Embedder, to_text : (Doc) -> String) -> EmbeddingStorage[Doc]
A fresh storage over embedder, extracting embeddable text from each document with to_text.
async fn[Doc] EmbeddingStorage::add( self : EmbeddingStorage[Doc], documents : Array[Doc]) -> Array[String]
Embed each document and store it, returning the assigned ids (Koog EmbeddingStorage.add).
async fn[Doc] EmbeddingStorage::search( self : EmbeddingStorage[Doc], query_text : String, limit? : Int = 10, offset? : Int = 0, min_score? : Double = 0.0) -> Array[SearchResult[Doc]]
Embed query_text and return the stored documents most similar to it, ranked by cosine similarity (Koog EmbeddingStorage.search). Raises @embeddings.VectorError on a dimension mismatch between the query and a stored document.
fn[Doc] EmbeddingStorage::get( self : EmbeddingStorage[Doc], id : String) -> Doc?
The document stored under id, or None.
fn[Doc] EmbeddingStorage::delete( self : EmbeddingStorage[Doc], id : String) -> Bool
Remove the document under id; returns whether it was present.
fn[Doc] EmbeddingStorage::size(self : EmbeddingStorage[Doc]) -> Int
The number of stored documents.
§Memory and persistence
What an agent remembers between runs, and where a run's checkpoints live.
enum FactType
Whether a concept holds one fact or many (Koog FactType).
struct Concept
A concept the agent remembers facts about: a short keyword, a description the model is shown, and whether it carries one fact or many. Transcribed from the koog Concept data class.
enum Fact
A fact about a concept, timestamped when captured (Koog's sealed Fact: SingleFact carries one value, MultipleFacts a list of values). The timestamp is caller-supplied — MoonBit has no ambient clock — the explicit equivalent of Koog threading a Clock into fact retrieval.
fn Fact::concept(self : Fact) -> Concept
The concept a fact is about, whichever variant it is.
struct MemorySubject
Who or what a fact is about (Koog MemorySubject): a name, and a priority for ordering when subjects overlap. The predefined subjects mirror Koog's.
let subject_everything : MemorySubject =
let subject_user : MemorySubject =
let subject_machine : MemorySubject =
let subject_organization : MemorySubject =
enum MemoryScope
How widely a fact is shared (Koog MemoryScope): to a single agent, a single feature, the whole product, or across products.
pub(open) trait MemoryProviderThe save/load contract for agent memory (Koog AgentMemoryProvider): store a fact under a subject and scope, load a concept's facts back, or load everything in a bucket.
struct InMemoryProvider
An in-memory MemoryProvider: facts kept in a map keyed by (scope, subject). The faithful equivalent of Koog's LocalFileMemoryProvider without the file backend — enough to run and test the memory contract in process.
fn InMemoryProvider::new() -> InMemoryProvider
An empty in-memory provider.
impl MemoryProvider for InMemoryProvider with fn save( self, fact, subject, scope)
impl MemoryProvider for InMemoryProvider with fn load( self, concept, subject, scope)
impl MemoryProvider for InMemoryProvider with fn load_all( self, subject, scope)
struct AgentCheckpoint
A snapshot of an agent's run at a node boundary (Koog AgentCheckpointData with its GraphCheckpointProperties): the conversation so far, the LLM configuration that produced it, the serialized AIAgentStorage, and where the strategy graph had reached — the node about to run (node_id) and the value flowing into it (last_input). Restoring replays message_history and resumes the walk at node_id. created_at is caller-supplied: MoonBit has no ambient clock, and a supplied one keeps a test's checkpoints deterministic.
fn AgentCheckpoint::new( checkpoint_id~ : String, created_at~ : Int64, node_id~ : String, message_history? : Array[@prompt.Message] = [], llm_params? : @prompt.LLMParams? = None, llm_model? : @llm.LLModel? = None, tools? : Array[String]? = None, storage? : Json = Json::object(
A checkpoint with only the fields a resume needs stated; the rest carry empty defaults, so a caller that keeps no LLM configuration or storage need not spell them out.
pub(open) trait PersistenceStorageProviderThe checkpoint storage contract (Koog PersistenceStorageProvider): save a checkpoint under a session, list a session's checkpoints, or fetch its latest.
struct InMemoryPersistence
An in-memory PersistenceStorageProvider (Koog InMemoryPersistencyStorageProvider): checkpoints kept per session in save order.
fn InMemoryPersistence::new() -> InMemoryPersistence
An empty in-memory checkpoint store.
fn InMemoryPersistence::save_checkpoint( self : InMemoryPersistence, session_id : String, checkpoint : AgentCheckpoint) -> Unit
Save checkpoint under session_id.
fn InMemoryPersistence::get_checkpoints( self : InMemoryPersistence, session_id : String) -> Array[AgentCheckpoint]
Every checkpoint saved for session_id, in save order.
fn InMemoryPersistence::get_latest_checkpoint( self : InMemoryPersistence, session_id : String) -> AgentCheckpoint?
The most recent checkpoint for session_id — the highest created_at, ties going to the last saved — or None when the session has none.
impl PersistenceStorageProvider for InMemoryPersistence with fn save_checkpoint( self, session_id, checkpoint)
impl PersistenceStorageProvider for InMemoryPersistence with fn get_checkpoints( self, session_id)
impl PersistenceStorageProvider for InMemoryPersistence with fn get_latest_checkpoint( self, session_id)
§MCP
Model Context Protocol both ways: expose this agent's tools to an MCP client, or call another server's tools as if they were local.
pub(open) trait McpTransportA synchronous MCP transport: send one JSON-RPC request, get its response (Koog Transport).
struct McpClient
An MCP client over transport, issuing JSON-RPC 2.0 calls with monotonically increasing ids.
fn McpClient::new(transport : &McpTransport) -> McpClient
A client that talks to an MCP server through transport.
fn McpClient::initialize(self : McpClient) -> Json raise
The MCP initialize handshake, advertising the client name and protocol version.
fn McpClient::list_tools(self : McpClient) -> Array[Json] raise
List the tools the MCP server exposes (tools/list), returning each tool definition's JSON.
fn McpClient::call_tool( self : McpClient, name : String, arguments : Json) -> Json raise
Call the MCP tool name with arguments (tools/call), returning the CallToolResult JSON.
struct McpServer
An MCP server exposing the tools in registry.
fn McpServer::new(registry : @tools.ToolRegistry) -> McpServer
A server advertising registry's tools over MCP.
fn McpServer::handle(self : McpServer, request : Json) -> Json
Handle one JSON-RPC request, returning the response — a result, or an error object when the method itself fails (a tool's own failure is a normal isError result, not a protocol error).
struct McpTool
A moonkoog tool backed by an MCP server tool (Koog McpTool).
fn McpTool::new( client : McpClient, desc : @tools.ToolDescriptor) -> McpTool
An MCP-backed tool calling desc.name on client.
impl @tools.Tool for McpTool with fn descriptor(self)
impl @tools.Tool for McpTool with fn execute_raw(self, args)
fn mcp_tool_registry(client : McpClient) -> @tools.ToolRegistry raise
Build a ToolRegistry from every tool an MCP server advertises (Koog McpToolRegistryProvider): initialize the connection, list the tools, parse each descriptor, and register a wrapping tool.
suberror McpErrorRaised on a malformed MCP tool schema or JSON-RPC response (Koog throws IllegalArgumentException).
fn parse_tool(tool : Json) -> @tools.ToolDescriptor raise
Parse an MCP tool definition into a ToolDescriptor (Koog DefaultMcpToolDescriptorParser.parse). The required names decide which parsed parameters are required and which are optional.
§A2A
Agent-to-Agent: the task model, the JSON-RPC dispatcher an executor sits behind, the agent card that advertises it, and the streaming and push-notification transports.
suberror A2AErrorRaised on a malformed A2A payload.
enum Role
Who authored a message (A2A Role).
enum FileContent
A file attachment, carried either inline as base64 bytes or by URI (A2A FileWithBytes / FileWithUri).
enum Part
One piece of a message: plain text, a file, or a structured data object (A2A Part).
struct Message
A message exchanged with an agent (A2A Message).
fn Message::user_text(message_id : String, text : String) -> Message
A user message with a single text part (the common case).
struct Artifact
A file/data artifact an agent produced while working a task (A2A Artifact).
enum TaskState
The lifecycle state of a task (A2A TaskState); terminal states admit no further transitions.
fn TaskState::terminal(self : TaskState) -> Bool
Whether the state is terminal (Koog TaskState.terminal): completed, canceled, failed, rejected.
fn TaskState::wire(self : TaskState) -> String
The wire (kebab-case @SerialName) form of the state.
fn TaskState::from_wire(s : String) -> TaskState
The state named by its wire form (unrecognised names map to Unknown).
struct TaskStatus
The status of a task: its state, an optional status message, and a timestamp (A2A TaskStatus).
struct Task
A unit of work an agent runs on a caller's behalf (A2A Task).
fn Part::to_json(self : Part) -> Json
fn Message::to_json(self : Message) -> Json
fn Artifact::to_json(self : Artifact) -> Json
fn TaskStatus::to_json(self : TaskStatus) -> Json
fn Task::to_json(self : Task) -> Json
fn Part::from_json(j : Json) -> Part raise
fn Message::from_json(j : Json) -> Message raise
fn Artifact::from_json(j : Json) -> Artifact raise
fn TaskStatus::from_json(j : Json) -> TaskStatus raise
fn Task::from_json(j : Json) -> Task raise
pub(open) trait A2ATransportA synchronous A2A transport: send one JSON-RPC request, get its response (Koog ClientTransport).
enum SendResult
The outcome of message/send: the agent either opened a task or replied with a message directly (A2A's result is a Task | Message union, discriminated by kind).
struct A2AClient
A client for a remote agent over transport, issuing JSON-RPC 2.0 calls with increasing ids.
fn A2AClient::new(transport : &A2ATransport) -> A2AClient
A client talking to the agent behind transport.
fn A2AClient::send_message( self : A2AClient, message : Message) -> SendResult raise
Send message to the agent (message/send), returning the task it opened or its direct reply.
fn A2AClient::get_task( self : A2AClient, task_id : String, history_length? : Int) -> Task raise
Fetch the current state of a task (tasks/get), optionally bounding the returned history.
fn A2AClient::cancel_task(self : A2AClient, task_id : String) -> Task raise
Request cancellation of a task (tasks/cancel), returning its updated state.
struct RequestContext
The context an executor runs a request in (Koog RequestContext): the incoming message, the task and context ids it belongs to, and the existing task when the message continues one.
pub(open) trait AgentExecutorThe agent's logic behind a server (Koog AgentExecutor): run a request to a result, or cancel a task.
pub(open) trait TaskStoreWhere a server keeps tasks between requests (Koog task storage).
struct InMemoryTaskStore
An in-memory task store (Koog InMemoryMessageStorage).
fn InMemoryTaskStore::new() -> InMemoryTaskStore
A fresh in-memory store.
impl TaskStore for InMemoryTaskStore with fn get(self, task_id)
impl TaskStore for InMemoryTaskStore with fn save(self, task)
struct A2AServer
An A2A server dispatching JSON-RPC requests to executor, persisting tasks in store and push-notification configs per task.
fn A2AServer::new( executor : &AgentExecutor, store : &TaskStore) -> A2AServer
A server backed by executor and store.
fn A2AServer::handle(self : A2AServer, request : Json) -> Json
Handle one JSON-RPC request, returning the JSON-RPC response — a result on success, or an error object when the method fails (a server answers, it does not throw at the transport).
struct AgentInterface
A transport endpoint the agent also serves on (A2A AgentInterface).
struct AgentProvider
The organization behind an agent (A2A AgentProvider).
struct AgentExtension
A protocol extension an agent supports (A2A AgentExtension).
struct AgentCapabilities
What optional protocol features an agent supports (A2A AgentCapabilities).
struct AgentSkill
One capability an agent advertises (A2A AgentSkill).
struct AgentCard
An agent's public description and discovery document (A2A AgentCard).
pub(open) trait CardSourceWhere an agent card is fetched from (Koog AgentCardResolver): typically an HTTP GET of the agent's well-known card URL, injectable so tests can supply a card without a network.
fn resolve_agent_card(source : &CardSource) -> AgentCard raise
Resolve and parse an agent's card from source (Koog A2AClient.getAgentCard).
fn AgentInterface::to_json(self : AgentInterface) -> Json
fn AgentProvider::to_json(self : AgentProvider) -> Json
fn AgentExtension::to_json(self : AgentExtension) -> Json
fn AgentCapabilities::to_json(self : AgentCapabilities) -> Json
fn AgentSkill::to_json(self : AgentSkill) -> Json
fn AgentCard::to_json(self : AgentCard) -> Json
fn AgentInterface::from_json(j : Json) -> AgentInterface raise
fn AgentProvider::from_json(j : Json) -> AgentProvider raise
fn AgentExtension::from_json(j : Json) -> AgentExtension raise
fn AgentCapabilities::from_json(j : Json) -> AgentCapabilities raise
fn AgentSkill::from_json(j : Json) -> AgentSkill raise
fn AgentCard::from_json(j : Json) -> AgentCard raise
struct TaskStatusUpdateEvent
A task's status changed while streaming (A2A TaskStatusUpdateEvent); is_final ends the stream.
struct TaskArtifactUpdateEvent
The agent produced (part of) an artifact while streaming (A2A TaskArtifactUpdateEvent).
enum StreamEvent
One event of a streamed response (A2A streaming Event union, discriminated by kind).
pub(open) trait EventStreamWhere a streamed response body comes from (the SSE side of Koog's ClientTransport): send the request, get back the whole SSE body. Injectable so the parsing is testable without a live socket.
fn TaskStatusUpdateEvent::to_json(self : TaskStatusUpdateEvent) -> Json
fn TaskStatusUpdateEvent::from_json( j : Json) -> TaskStatusUpdateEvent raise
fn TaskArtifactUpdateEvent::to_json(self : TaskArtifactUpdateEvent) -> Json
fn TaskArtifactUpdateEvent::from_json( j : Json) -> TaskArtifactUpdateEvent raise
fn StreamEvent::from_json(j : Json) -> StreamEvent raise
Parse a streamed event from its JSON, dispatching on kind.
fn stream_message( source : &EventStream, message : Message) -> Array[StreamEvent] raise
Send message and collect the streamed events (message/stream): open the SSE stream, parse each data: frame as a JSON-RPC response, and turn each result into a StreamEvent.
struct SseEvent
One dispatched SSE event: its type (default message), its data payload, and the last seen id.
fn parse_sse(text : String) -> Array[SseEvent]
Parse an SSE stream body into its dispatched events (WHATWG EventSource interpretation).
struct PushAuthInfo
How the agent authenticates its callback to the caller (A2A PushNotificationAuthenticationInfo).
struct PushNotificationConfig
A webhook the agent calls on task updates (A2A PushNotificationConfig).
struct TaskPushConfig
A push-notification config bound to a task (A2A TaskPushNotificationConfig).
fn PushAuthInfo::to_json(self : PushAuthInfo) -> Json
fn PushAuthInfo::from_json(j : Json) -> PushAuthInfo raise
fn PushNotificationConfig::to_json(self : PushNotificationConfig) -> Json
fn PushNotificationConfig::from_json( j : Json) -> PushNotificationConfig raise
fn TaskPushConfig::to_json(self : TaskPushConfig) -> Json
fn TaskPushConfig::from_json(j : Json) -> TaskPushConfig raise
fn A2AClient::set_push_config( self : A2AClient, config : TaskPushConfig) -> TaskPushConfig raise
Register a push-notification webhook for a task (tasks/pushNotificationConfig/set).
fn A2AClient::get_push_config( self : A2AClient, task_id : String, config_id? : String) -> TaskPushConfig raise
Read a task's push-notification config (tasks/pushNotificationConfig/get).
fn A2AClient::list_push_configs( self : A2AClient, task_id : String) -> Array[TaskPushConfig] raise
List a task's push-notification configs (tasks/pushNotificationConfig/list).
fn A2AClient::delete_push_config( self : A2AClient, task_id : String, config_id : String) -> Unit raise
Delete a task's push-notification config (tasks/pushNotificationConfig/delete).