Skip to content

API Reference

This page is a curated entry point into the public API. For higher-level behavior and composition, start with the guide pages first.

Agent

Krill.AgentModule.Agent Type
julia
Agent(provider; kwargs...)

Encapsulates all LLM-related configuration for a Krill agent. Use with RuntimeState(channels, agent) for a cleaner alternative to passing 50+ llm_* keyword arguments directly to RuntimeState.

Basic usage

julia
agent = Agent(OpenAIProvider(api_key=ENV["OPENAI_API_KEY"], model="gpt-4o-mini");
    system_prompt = "You are a helpful assistant.",
    workspace    = "context",
)
rt = RuntimeState(channels, agent)

With hooks and custom retry

julia
agent = Agent(provider;
    hooks = AgentHooks(
        on_tool_call   = (name, args) -> @info "Tool" name,
        on_tool_result = (name, res)  -> @info "Result" name chars=length(res),
        should_interrupt = (name, _)  -> name == "forbidden_tool",
    ),
    retry = RetryConfig(max_retries=5, base_delay_s=1.0),
)

With config structs

julia
agent = Agent(provider;
    memory       = MemoryConfig(enable=true, enable_consolidation=false),
    builtin_tools = BuiltinToolsConfig(enable_exec=true, exec_timeout_s=30.0),
    claude_code  = ClaudeCodeConfig(enable=true, model="opus"),
)
source
Krill.AgentModule.AgentHooks Type
julia
AgentHooks(; on_turn_start, on_turn_end, on_tool_call, on_tool_result, should_interrupt)

Lifecycle callbacks injected into the agent loop. All fields are optional.

HookSignatureCalled when
on_turn_start(msg, history) -> nothingBefore each LLM call, after typing indicator
on_turn_end(msg, history) -> nothingAfter response is persisted and outbound queued
on_tool_call(tool_name, arguments) -> nothingBefore each tool is dispatched
on_tool_result(tool_name, result_text) -> nothingAfter a successful tool dispatch
should_interrupt(tool_name, arguments) -> BoolBefore each tool; return true to stop the loop

Hook failures are logged with @warn and never propagate. Hooks are not thread-safe by default — close over shared mutable state with care in concurrent sessions.

When should_interrupt returns true, remaining tool calls in the current LLM batch are silently skipped and the loop exits with the current response text.

source
Krill.AgentModule.RetryConfig Type
julia
RetryConfig(; max_retries, base_delay_s, max_delay_s, multiplier, jitter, retriable_status_codes)

Retry policy for LLM API calls. Applies exponential backoff with optional jitter.

FieldDefaultMeaning
max_retries3Maximum number of retry attempts after the first failure
base_delay_s0.5Initial delay in seconds before the first retry
max_delay_s60.0Cap on per-attempt sleep duration
multiplier2.0Exponential growth factor per attempt
jittertrueRandomise sleep by 0.75–1.0× to avoid thundering herd
retriable_status_codes{408,429,500,502,503,504,529}HTTP status codes that trigger a retry

Sleep formula: clamp(base_delay_s × multiplier^(attempt-1) × jitter_factor, 0, max_delay_s)

source

Runtime

Krill.RuntimeModule.RuntimeState Type
julia
RuntimeState(channels; hub, consumer, store, processor, workspace, llm_mcp_servers, ...)

Top-level runtime that owns the full message pipeline: channel inbound polling, normalization with dedup, session-aware consumer processing (echo by default), and outbound dispatch.

Accepts a single AbstractChannel or a Vector{<:AbstractChannel}.

Use start! and shutdown! to manage the lifecycle.

source
Krill.RuntimeModule.start! Function
julia
start!(rt::RuntimeState) -> rt

Start all channel inbound loops, consumer, and dispatch tasks. No-op if already running.

source
Krill.RuntimeModule.shutdown! Function
julia
shutdown!(rt::RuntimeState) -> rt

Gracefully shut down the runtime. Stops all channel inbound loops first (no new messages), then waits for the consumer to drain inbound, then stops outbound dispatch.

source

Message Contracts

Krill.Types.ContentPart Type
julia
ContentPart

Abstract supertype for message content parts. Concrete subtypes: TextPart, BinaryPart, ToolCallPart, ToolResultPart.

source
Krill.Types.TextPart Type
julia
TextPart(text::String)

Plain text content within a message.

source
Krill.Types.BinaryPart Type
julia
BinaryPart(media_type, url, bytes, filename)

Binary media content (image, audio, document, etc.) within a message.

source
Krill.Types.ToolCallPart Type
julia
ToolCallPart(tool_name, arguments)

Records a tool invocation request within a message.

source
Krill.Types.ToolResultPart Type
julia
ToolResultPart(tool_name, result, is_error)

Records a tool execution result within a message.

source
Krill.Types.DeliveryPolicy Type
julia
DeliveryPolicy(; max_retries=3, timeout_ms=30_000, priority=0, drop_if_late=false)

Controls outbound message delivery behaviour — retry budget, timeout, priority, and whether the message may be silently dropped if delivery is late.

Throws ArgumentError if max_retries or timeout_ms is negative.

source
Krill.Types.ErrorEnvelope Type
julia
ErrorEnvelope(code, message, retriable, details)

Structured error representation propagated through the runtime. retriable indicates whether the caller should attempt a retry.

source
Krill.Types.InboundMessage Type
julia
InboundMessage(; channel, session_key, user_id, chat_id, text, ...)

A message arriving from an external channel (user → runtime).

Required keyword arguments: channel, session_key, user_id, chat_id, text. All other fields have sensible defaults (auto-generated UUIDs, current UTC timestamp, etc.).

source
Krill.Types.OutboundMessage Type
julia
OutboundMessage(; channel, session_key, chat_id, text, ...)

A message leaving the runtime toward an external channel (runtime → user).

Required keyword arguments: channel, session_key, chat_id, text.

source
Krill.Types.ToolCallEvent Type
julia
ToolCallEvent(; session_key, tool_name, arguments=Dict(), ...)

Event recording a tool invocation request within a session.

source
Krill.Types.ToolResultEvent Type
julia
ToolResultEvent(; session_key, tool_name, result=nothing, error=nothing, ...)

Event recording the outcome of a tool execution. Carries either result (on success) or error (ErrorEnvelope).

source
Krill.Types.message_text Function
julia
message_text(msg::Union{InboundMessage, OutboundMessage}) -> String

Extract and concatenate all TextPart content from a message, joining multiple parts with newlines.

source

Queues and Dispatch

Krill.MessageHub.MessageHubState Type
julia
MessageHubState(; inbound_capacity=32, outbound_capacity=32)

Typed FIFO message queues that decouple producers from consumers. Inbound queue carries InboundMessage, outbound carries OutboundMessage.

Throws ArgumentError if either capacity is not positive.

source
Krill.MessageHub.publish_inbound! Function
julia
publish_inbound!(hub, msg)

Enqueue an InboundMessage. Blocks if the inbound channel is full.

source
Krill.MessageHub.publish_outbound! Function
julia
publish_outbound!(hub, msg)

Enqueue an OutboundMessage. Blocks if the outbound channel is full.

source
Krill.MessageHub.try_publish_inbound! Function
julia
try_publish_inbound!(hub, msg) -> Bool

Non-blocking enqueue. Returns true if the message was published, false if the inbound queue is full. Safe for single-producer use.

source
Krill.MessageHub.try_publish_outbound! Function
julia
try_publish_outbound!(hub, msg) -> Bool

Non-blocking enqueue. Returns true if the message was published, false if the outbound queue is full. Safe for single-producer use.

source
Krill.MessageHub.take_inbound! Function
julia
take_inbound!(hub) -> InboundMessage

Dequeue the next inbound message. Blocks until one is available.

source
Krill.MessageHub.take_outbound! Function
julia
take_outbound!(hub) -> OutboundMessage

Dequeue the next outbound message. Blocks until one is available.

source
Krill.MessageHub.try_take_inbound! Function
julia
try_take_inbound!(hub) -> Union{InboundMessage, Nothing}

Non-blocking dequeue. Returns nothing if the inbound queue is empty.

source
Krill.MessageHub.try_take_outbound! Function
julia
try_take_outbound!(hub) -> Union{OutboundMessage, Nothing}

Non-blocking dequeue. Returns nothing if the outbound queue is empty.

source
Krill.ChannelManager.ChannelManagerState Type
julia
ChannelManagerState(hub::MessageHubState; on_dispatch=nothing, dead_letter_path=nothing)

Manages channel sender registration and asynchronous outbound message dispatch. Consumes messages from the hub's outbound queue and routes each to the sender registered for that message's channel symbol.

Optional callbacks:

  • on_dispatch: called with a DispatchEvent after every delivery attempt

  • dead_letter_path: file path for persistent dead-letter log (JSONL)

Use register_sender! to associate a channel name with a send function, then start_dispatch! / stop_dispatch! to control the dispatch loop.

source
Krill.ChannelManager.DispatchEvent Type
julia
DispatchEvent

Emitted after each dispatch attempt. Passed to the optional on_dispatch callback.

Fields:

  • message_id: UUID of the outbound message

  • correlation_id: UUID of the inbound message that triggered this outbound (or nothing)

  • channel: target channel symbol

  • session_key: session that produced this message

  • chat_id: target chat

  • outcome: :delivered, :failed, :dropped, or :no_sender

  • reason: human-readable reason (empty on success)

  • attempts: number of send attempts made

  • elapsed_ms: wall-clock time spent on delivery

  • error: the last error (or nothing)

  • timestamp: when the event was recorded

source
Krill.ChannelManager.register_sender! Function
julia
register_sender!(manager, channel::Symbol, sender::Function)

Register sender as the delivery function for channel. sender will be called with a single OutboundMessage argument. Overwrites any previously registered sender for the same channel.

source
Krill.ChannelManager.start_dispatch! Function
julia
start_dispatch!(manager) -> manager

Start the background dispatch loop. Messages on the hub's outbound queue are consumed and routed to the appropriate registered sender.

No-op if dispatch is already running.

source
Krill.ChannelManager.stop_dispatch! Function
julia
stop_dispatch!(manager) -> manager

Signal the dispatch loop to stop. The loop drains any remaining outbound messages before exiting. The hub's outbound channel remains open and usable.

source
Krill.ChannelManager.dispatch_stats Function
julia
dispatch_stats(manager) -> Dict{String,Any}

Return delivery statistics: counts, last success time, dead letter count.

source
Krill.ChannelManager.dead_letters Function
julia
dead_letters(manager) -> Vector{Dict{String,Any}}

Return a copy of the dead-letter log.

source
Krill.ChannelManager.flush_dead_letters! Function
julia
flush_dead_letters!(manager) -> Vector{Dict{String,Any}}

Return and clear the dead-letter log.

source
Krill.Dedup.BoundedDedup Type
julia
BoundedDedup(capacity=1000)

Bounded set for deduplicating integer IDs (e.g. Telegram update_id). Stores up to capacity entries; when full, the oldest entry is evicted.

Use seen! to record an ID and check if it was already known, and has_seen for a read-only membership check.

source
Krill.Dedup.seen! Function
julia
seen!(d::BoundedDedup, id::Int) -> Bool

Record id and return true if it is new (first time seen). Return false if it was already in the set (duplicate).

source
Krill.Dedup.has_seen Function
julia
has_seen(d::BoundedDedup, id::Int) -> Bool

Return true if id has been recorded, false otherwise.

source

Channels

Krill.ChannelInterface.AbstractChannel Type
julia
AbstractChannel

Abstract supertype for all channel implementations.

Every concrete channel must implement:

  • channel_name(ch) -> Symbol — unique channel identifier (e.g. :telegram, :discord)

  • make_sender(ch) -> Function — returns (OutboundMessage) -> Any sender function

  • normalize(ch, raw_event) -> Union{InboundMessage, Nothing} — converts raw platform event to InboundMessage

  • start_channel!(ch, hub, running; dedup, on_message) -> Task — starts the inbound event loop, returns the polling/gateway task

  • stop_channel!(ch) -> Nothing — stops the channel (cleanup connections, etc.)

Optional:

  • send_typing(ch, chat_id) -> Nothing — sends typing indicator (default: no-op)

  • send_direct(ch, chat_id, text; kwargs...) -> Any — sends a message directly bypassing the outbound queue (for tools, progress hints)

source
Krill.ChannelInterface.ChannelState Type
julia
ChannelState

Tracks a registered channel within the runtime — holds the channel instance, its sender, and the inbound task.

source
Krill.ChannelInterface.channel_name Function
julia
channel_name(ch::AbstractChannel) -> Symbol

Return the unique channel identifier symbol (e.g. :telegram, :discord).

source
Krill.ChannelInterface.make_sender Function
julia
make_sender(ch::AbstractChannel) -> Function

Return a sender function (OutboundMessage) -> Any suitable for register_sender!.

source
Krill.ChannelInterface.normalize Function
julia
normalize(ch::AbstractChannel, raw_event) -> Union{InboundMessage, Nothing}

Convert a raw platform event into an InboundMessage. Returns nothing if the event is not a recognizable message.

source
Krill.ChannelInterface.register_channel! Function
julia
register_channel!(manager::ChannelManagerState, ch::AbstractChannel;
                  on_send::Union{Nothing,Function}=nothing) -> ChannelState

Register a channel's sender with the ChannelManager. If on_send is provided, it wraps the sender to call on_send() after each successful send (e.g. to update last_successful_send_at).

Returns a ChannelState ready for start_channel!.

source
Krill.ChannelInterface.make_inbound_handler Function
julia
make_inbound_handler(ch::AbstractChannel, hub::MessageHubState;
                     dedup::Union{Nothing,BoundedDedup}=nothing,
                     on_poll::Union{Nothing,Function}=nothing) -> Function

Create a standard inbound handler function that normalizes, deduplicates, and publishes events to the hub. Channels can use this in their start_channel! implementation.

on_poll is called on every raw event before normalization (e.g. to update last_successful_poll_at).

source
Krill.ChannelInterface.start_channel! Function
julia
start_channel!(ch::AbstractChannel, hub::MessageHubState, running::Ref{Bool};
               dedup::Union{Nothing,BoundedDedup}=nothing,
               on_message::Union{Nothing,Function}=nothing) -> Task

Start the channel's inbound event loop (polling, WebSocket gateway, etc.). Returns the spawned Task.

The default implementation provides a standard inbound handler that:

  1. Normalizes raw events via normalize(ch, event)

  2. Deduplicates via dedup (if provided)

  3. Publishes to the hub's inbound queue

Channels that need custom event loop behavior should override this method.

source
Krill.ChannelInterface.stop_channel! Function
julia
stop_channel!(ch::AbstractChannel) -> Nothing

Stop the channel and clean up resources. Called during runtime shutdown. Default implementation is a no-op.

source
Krill.ChannelInterface.send_typing Function
julia
send_typing(ch::AbstractChannel, chat_id) -> Nothing

Send a typing indicator to the given chat. Default is a no-op.

source
Krill.ChannelInterface.send_direct Function
julia
send_direct(ch::AbstractChannel, chat_id, text::AbstractString; kwargs...) -> Any

Send a message directly to a chat, bypassing the outbound queue. Used by tools and progress hints. Default throws an error.

source
Krill.Channels.Telegram.TelegramClient Type
julia
TelegramClient(token; base_url=nothing, request=HTTP.request)

HTTP client for the Telegram Bot API. request is injectable for testing (any function with the same signature as HTTP.request).

source
Krill.Channels.Telegram.TelegramAPIError Type
julia
TelegramAPIError <: Exception

Raised when a Telegram Bot API call fails at either the HTTP or API level.

source
Krill.Channels.Telegram.TelegramChannel Type
julia
TelegramChannel(client::TelegramClient; poll_timeout=30, poll_interval=0.1)

Channel adapter wrapping a TelegramClient to implement the AbstractChannel interface. Handles polling, normalization, sending, and typing indicators.

source
Krill.Channels.Telegram.TelegramWebhookChannel Type
julia
TelegramWebhookChannel(client; url, host="0.0.0.0", port=8443, path="/webhook",
                       secret_token=nothing, set_webhook_on_start=true,
                       delete_webhook_on_stop=true, drop_pending_updates=false)

Channel adapter that receives Telegram updates via webhook HTTP POST instead of long-polling. The channel starts an embedded HTTP server on host:port and optionally registers the webhook URL with Telegram on start_channel!.

secret_token is used for both the setWebhook call and for verifying incoming requests via the X-Telegram-Bot-Api-Secret-Token header.

url is the publicly-reachable HTTPS URL that Telegram will POST to. It must include the path component (e.g. https://example.com/webhook).

source
Krill.Channels.Telegram.get_updates Function
julia
get_updates(client; offset=0, timeout=30, limit=nothing, allowed_updates=nothing)

Long-poll for new updates from the Telegram Bot API. Returns the raw array of update objects.

source
Krill.Channels.Telegram.send_message Function
julia
send_message(client, chat_id, text; parse_mode="HTML", disable_web_page_preview=false)

Send a text message to chat_id. Returns the sent message object from Telegram.

source
Krill.Channels.Telegram.send_chat_action Function
julia
send_chat_action(client, chat_id, action="typing")

Send a chat action (for example "typing") to indicate bot activity. Returns the API result.

source
Krill.Channels.Telegram.set_webhook Function
julia
set_webhook(client, url; secret_token=nothing, max_connections=nothing, allowed_updates=nothing, drop_pending_updates=false)

Register a webhook URL with Telegram. The bot will receive updates via HTTPS POST to this URL instead of via getUpdates long-polling.

secret_token (optional) is sent in the X-Telegram-Bot-Api-Secret-Token header of each webhook request so you can verify authenticity.

source
Krill.Channels.Telegram.delete_webhook Function
julia
delete_webhook(client; drop_pending_updates=false)

Remove the current webhook. After this, you can switch back to getUpdates polling.

source
Krill.Channels.Telegram.run_polling Function
julia
run_polling(client, handler; offset=0, timeout=30, poll_interval=0.1, max_updates=nothing)

Poll for Telegram updates in a loop, calling handler(update) for each one. If max_updates is set, stops after that many updates have been processed.

Handler exceptions are logged and do not terminate the polling loop.

source
Krill.Channels.Telegram.make_telegram_sender Function
julia
make_telegram_sender(client::TelegramClient) -> Function

Return a sender function suitable for register_sender!. The returned function takes an OutboundMessage and sends its text content to the appropriate chat via the Telegram Bot API.

source
Krill.Channels.Discord.DiscordChannel Type
julia
DiscordChannel(client::DiscordClient; intents=DEFAULT_INTENTS)
DiscordChannel(token; kwargs...)

Channel adapter wrapping a DiscordClient to implement the AbstractChannel interface. Connects to the Discord Gateway via WebSocket for receiving events and uses the REST API for sending messages.

source
Krill.Channels.Discord.discord_send_message Function
julia
discord_send_message(client, channel_id, content; kwargs...) -> Any

Send a text message to a Discord channel.

source
Krill.Channels.Discord.discord_trigger_typing Function
julia
discord_trigger_typing(client, channel_id) -> Nothing

Trigger the typing indicator in a Discord channel.

source

Sessions and Memory

Krill.Sessions.TurnRecord Type
julia
TurnRecord

A single turn in session history. Stored as one JSONL line on disk.

source
Krill.Sessions.SessionStore Type
julia
SessionStore(; workspace="workspace")

Manages per-session locks and JSONL history persistence. Sessions are identified by session_key strings. History files live at workspace/sessions/<sanitized_key>/history.jsonl.

Thread-safe: the lock map is protected by its own ReentrantLock.

source
Krill.Sessions.get_session_lock! Function
julia
get_session_lock!(store, session_key) -> ReentrantLock

Get or create the per-session lock. Thread-safe.

source
Krill.Sessions.load_history Function
julia
load_history(store, session_key) -> Vector{TurnRecord}

Load session history from the JSONL file. Returns empty vector if no file exists. Caller must hold the session lock.

source
Krill.Sessions.append_turn! Function
julia
append_turn!(store, session_key, turn)

Append a single turn to the session's JSONL history file. Caller must hold the session lock.

source
Krill.Sessions.save_history Function
julia
save_history(store, session_key, history)

Overwrite the session's JSONL history file. Useful for truncation/compaction. Caller must hold the session lock.

source
Krill.Sessions.session_dir Function
julia
session_dir(store, session_key) -> String

Return the directory path for a session's data files. Creates it if missing.

source
Krill.Sessions.sanitize_session_key Function
julia
sanitize_session_key(key) -> String

Replace characters invalid in file paths (: / \) with _.

source
Krill.Memory.MemoryState Type
julia
MemoryState

Per-session memory bookkeeping. last_consolidated tracks the last archived turn index/offset. consolidation_failures counts consecutive LLM failures for fallback logic.

source
Krill.Memory.MemoryStore Type
julia
MemoryStore(; workspace="workspace")

Persists per-session memory files under: workspace/memory/<sanitized_session_key>/.

source
Krill.Memory.memory_dir Function
julia
memory_dir(store, session_key) -> String

Return the session memory directory, creating it if needed.

source
Krill.Memory.load_memory Function
julia
load_memory(store, session_key) -> String

Read MEMORY.md for a session. Returns an empty string if missing.

source
Krill.Memory.save_memory! Function
julia
save_memory!(store, session_key, content)

Overwrite a session's MEMORY.md.

source
Krill.Memory.append_history! Function
julia
append_history!(store, session_key, entry; timestamp=now(UTC))

Append a timestamped block to HISTORY.md.

source
Krill.Memory.load_memory_state Function
julia
load_memory_state(store, session_key) -> MemoryState

Load memory state for a session. Missing or invalid files return defaults.

source
Krill.Memory.save_memory_state! Function
julia
save_memory_state!(store, session_key, state)

Persist per-session memory state metadata.

source
Krill.SessionConsumer.SessionCancelScope Type
julia
SessionCancelScope()

Cooperative cancellation registry for mid-turn /stop support. Each session key maps to an Atomic{Bool} flag. The LLM processor's stop_check reads this flag between tool iterations.

source
Krill.SessionConsumer.request_cancel! Function
julia
request_cancel!(scope, session_key) -> Bool

Set the cancellation flag for a session. Returns true if a flag existed (meaning a turn was in progress), false otherwise.

source
Krill.SessionConsumer.is_cancelled Function
julia
is_cancelled(scope, session_key) -> Bool

Check the cancellation flag for a session without clearing it.

source
Krill.SessionConsumer.clear_cancel! Function
julia
clear_cancel!(scope, session_key) -> Threads.Atomic{Bool}

Clear the cancellation flag and return a fresh atomic for the new turn. Call this at the start of each turn.

source
Krill.SessionConsumer.run_session_loop! Function
julia
run_session_loop!(hub, running; store, processor, before_process, after_process)

Session-aware consumer loop. For each inbound message, spawns a task that processes it under the session lock. Different sessions run in parallel; same-session messages are processed in FIFO order by chaining tasks.

Drains remaining inbound messages sequentially on shutdown. before_process runs before the processor call. after_process runs after user+assistant turns are persisted and outbound is queued.

source
Krill.SessionConsumer.echo_processor Function
julia
echo_processor(msg, history) -> String

Trivial processor that echoes the inbound message text. Placeholder for the Phase C LLM integration.

source
Krill.MemoryConsolidation.MemoryConsolidatorConfig Type
julia
MemoryConsolidatorConfig(; unconsolidated_token_threshold=2_000, max_output_tokens=800, max_input_turn_chars=2_000, max_consolidation_turns=50, max_failures=3)

Configuration for memory consolidation.

  • max_consolidation_turns: cap how many turns are sent to the LLM in a single consolidation call. Remaining turns are left for the next round.

  • max_failures: after this many consecutive LLM failures, raw-dump turns to HISTORY.md and advance last_consolidated without an LLM summary.

source
Krill.MemoryConsolidation.consolidate_session_memory! Function
julia
consolidate_session_memory!(provider, memory_store, session_key, history; config=MemoryConsolidatorConfig())

Consolidate unconsolidated session turns into MEMORY.md when their estimated token count exceeds the configured threshold. Appends raw archived turns into HISTORY.md and advances last_consolidated state.

At most config.max_consolidation_turns turns are processed per call; remaining turns are left for the next invocation.

After config.max_failures consecutive LLM failures, falls back to a raw dump of turns into HISTORY.md (no LLM summary) so that last_consolidated advances and the consolidation prompt doesn't grow unboundedly.

source
Krill.MemoryConsolidation.make_memory_consolidator Function
julia
make_memory_consolidator(provider, memory_store; kwargs...) -> Function

Create an after_process(msg, history) hook for run_session_loop!.

source

Tools and Skills

Krill.Tools.ToolDef Type
julia
ToolDef(; name, parameters, execute, description=nothing, return_direct=false, max_output_chars=0, strict=nothing)

Defines a callable tool with JSON-schema parameters and execution behavior. execute receives a Dict{String,Any} of validated arguments.

source
Krill.Skills.SkillDef Type
julia
SkillDef

A discovered skill with metadata parsed from SKILL.md frontmatter.

Fields:

  • name: directory name

  • description: from frontmatter or first non-heading line

  • path: absolute path to SKILL.md

  • source: "workspace" or "builtin"

  • always: if true, full content is auto-injected into system prompt

  • available: whether all requirements (bins, env vars) are met

  • missing_requirements: human-readable list of unmet requirements

source
Krill.Skills.load_always_skills Function
julia
load_always_skills(skills) -> Union{Nothing, String}

Load full content of all always-on, available skills. Returns formatted text for injection into the system prompt, or nothing if no always-on skills exist. Frontmatter is stripped from the content.

source
Krill.BuiltinTools.register_builtin_tools! Function
julia
register_builtin_tools!(registry; workspace="workspace", enable_exec=false, ...) -> Vector{ToolDef}

Register the standard set of built-in tools (file ops, web fetch, exec, github, message, claude_code, codex, google_workspace) into the given ToolRegistry.

source

Prompt Context

Krill.PromptContext.BootstrapDoc Type
julia
BootstrapDoc

Loaded bootstrap context document.

source
Krill.PromptContext.load_bootstrap_docs Function
julia
load_bootstrap_docs(workspace; doc_names=DEFAULT_BOOTSTRAP_DOCS, max_chars_per_doc=12_000)

Load bootstrap docs from workspace, in listed order. Missing files are skipped.

source
Krill.PromptContext.render_runtime_metadata Function
julia
render_runtime_metadata(msg; now_fn=() -> now(UTC)) -> String

Render runtime metadata for prompt context.

source
Krill.PromptContext.compose_instructions Function
julia
compose_instructions(base_instructions; bootstrap_docs, skills_summary_text, always_skills_text, memory_text, include_tool_safety, runtime_metadata_text)

Compose final instructions by appending non-empty sections with separators. When include_tool_safety is true, appends TOOL_OUTPUT_SAFETY_NOTICE.

source
Krill.PromptContext.make_prompt_builder Function
julia
make_prompt_builder(; bootstrap_docs, skills_summary_text, always_skills_text, include_runtime_metadata, include_tool_safety, now_fn)

Create a prompt builder callback compatible with make_llm_processor(...; instructions_builder=...).

source

LLM Providers

Krill.LLM.AbstractLLMProvider Type
julia
AbstractLLMProvider

Abstract supertype for LLM API providers (OpenAI, Gemini, etc.).

source
Krill.LLM.OpenAIProvider Type
julia
OpenAIProvider(; api_key, base_url, model, request, max_retries, retry_base_seconds)

Minimal OpenAI Responses API provider backed by HTTP.request.

source
Krill.LLM.OpenAIAPIError Type
julia
OpenAIAPIError <: Exception

Error raised for OpenAI API failures. retriable=true indicates the error is suitable for retry with backoff.

source
Krill.LLM.GeminiProvider Type
julia
GeminiProvider(; api_key, base_url, model, request, max_retries, retry_base_seconds)

Native Gemini API provider backed by HTTP.request and POST /v1beta/models/{model}:generateContent.

Reference: https://ai.google.dev/api/rest/v1beta/models/generateContent

source
Krill.LLM.GeminiOpenAICompatProvider Type
julia
GeminiOpenAICompatProvider(; api_key, base_url, model, request, max_retries, retry_base_seconds, extra_body)

Gemini provider using Google's OpenAI-compatible chat/completions endpoint.

Reference: https://ai.google.dev/gemini-api/docs/openai

source
Krill.LLM.LLMUsage Type
julia
LLMUsage

Token accounting summary for a response.

source
Krill.LLM.LLMToolCall Type
julia
LLMToolCall

Normalized function/tool call request returned by providers.

source
Krill.LLM.LLMResponse Type
julia
LLMResponse

LLM response payload with extracted text plus raw OpenAI response object.

source
Krill.LLM.chat_completion Function
julia
chat_completion(provider, input; kwargs...) -> LLMResponse

Call OpenAI's POST /v1/responses endpoint. input should be either a string or a Responses API input message array.

Reference: https://platform.openai.com/docs/api-reference/responses

source
Krill.LLM.make_llm_processor Function
julia
make_llm_processor(provider; kwargs...) -> Function

Create a session processor compatible with run_session_loop!. Supports text/image/file inputs (from content_parts) and Responses API tools options. When memory_store is provided, session memory is loaded and appended to context instructions for each turn. When instructions_builder is provided, it receives (msg, base_instructions, memory_text) and can compose per-turn instructions (for runtime metadata/bootstrap docs/memory policy). When enable_history_summarization is true, turns that are dropped due to context window limits are summarized by the LLM and prepended to instructions.

source

MCP

Krill.MCP.MCPServer Type
julia
MCPServer(; name, transport=:auto, command=nothing, args=String[], env=Dict(), url=nothing,
            headers=Dict(), request_timeout_s=30.0, tool_timeout_s=30.0,
            enabled_tools=["*"], cache_tools=true)

MCP server configuration for either stdio or HTTP transport.

  • name: logical server name used for namespaced tool IDs.

  • transport: :auto, :stdio, :sse, or :streamable_http.

  • enabled_tools: allowlist of tool names; accepts raw names or wrapped names. Use ["*"] (default) for all tools, or String[] for none.

source

Cron

Krill.Cron.CronJob Type

A scheduled job definition.

source
Krill.Cron.CronService Type
julia
CronService(; workspace, tick_interval_s, publish_fn)

In-process job scheduler. Runs a background tick loop that checks all registered jobs and fires due ones by injecting InboundMessage into the message hub via publish_fn.

publish_fn should be a function (InboundMessage) -> Bool (e.g., try_publish_inbound! bound to a hub).

source
Krill.Cron.add_job! Function

Add a job to the service. Returns the job.

source
Krill.Cron.remove_job! Function

Remove a job by ID. Returns true if found and removed.

source
Krill.Cron.list_jobs Function

List all jobs.

source
Krill.Cron.get_job Function

Get a job by ID.

source
Krill.Cron.is_due Function

Check if a job is due to fire at the given time.

source
Krill.Cron.parse_schedule Function

Parse a schedule from a type string and value.

source
Krill.Cron.parse_cron Function

Parse a standard 5-field cron expression into a CronSchedule.

source
Krill.Cron.save_jobs! Function

Persist all jobs to disk.

source
Krill.Cron.load_jobs! Function

Load jobs from disk. Silently no-ops if file doesn't exist.

source

Subagents

Krill.Subagent.SubagentTask Type
julia
SubagentTask

Tracks a single spawned subagent background task.

source
Krill.Subagent.SubagentManager Type
julia
SubagentManager

Manages spawned subagent background tasks. Provides spawn, cancel, and listing operations. Each subagent runs its own LLM conversation loop with a restricted tool set (no spawn, no message, no cron).

source
Krill.Subagent.spawn_subagent! Function
julia
spawn_subagent!(mgr, task_description; label, origin_channel, origin_session_key, origin_chat_id) -> String

Spawn a background subagent to execute the given task. Returns immediately with a status message. The subagent runs its own LLM conversation loop and announces results back to the origin session via the shared message hub.

source
Krill.Subagent.cancel_subagents! Function
julia
cancel_subagents!(mgr, session_key) -> Int

Cancel all running subagents for the given session. Returns the number cancelled.

source
Krill.Subagent.list_subagents Function
julia
list_subagents(mgr; session_key=nothing) -> Vector{SubagentTask}

List subagent tasks, optionally filtered by session.

source
Krill.Subagent.subagent_count Function
julia
subagent_count(mgr; running_only=false) -> Int
source
Krill.Subagent.register_spawn_tools! Function
julia
register_spawn_tools!(registry, mgr; from_subagent=false, replace=false) -> Vector{ToolDef}

Register spawn, spawn_list, spawn_cancel tools. If from_subagent=true, tools are not registered (prevents recursive spawning).

source

Durable Queue

Krill.DurableQueue.DurableQueueState Type
julia
DurableQueueState(; wal_path, auto_compact_threshold=1000)

Append-only WAL (write-ahead log) for crash-recoverable message queuing.

Each entry is a JSONL line with op = "enqueue" or "ack". On startup, call replay(dq) to recover unacked messages.

auto_compact_threshold: when the WAL exceeds this many lines, compact! is called automatically on the next ack!.

source
Krill.DurableQueue.enqueue! Function
julia
enqueue!(dq, msg::Union{InboundMessage, OutboundMessage})

Persist a message to the WAL before processing. Returns the message_id.

source
Krill.DurableQueue.ack! Function
julia
ack!(dq, message_id::UUID)

Mark a message as successfully processed. Triggers auto-compaction if threshold exceeded.

source
Krill.DurableQueue.replay Function
julia
replay(dq) -> (inbound=Vector{InboundMessage}, outbound=Vector{OutboundMessage})

Read the WAL and return all unacked messages, preserving original order. Call this on startup to recover messages that were enqueued but not acked.

source
Krill.DurableQueue.compact! Function
julia
compact!(dq)

Rewrite the WAL, removing all acked entries. This reduces file size.

source
Krill.DurableQueue.queue_stats Function
julia
queue_stats(dq) -> Dict{String,Any}
source