Skip to main content

Crate okbot_core

Crate okbot_core 

Source
Expand description

Domain model and ports (traits) of okbot; the SDK for third-party adapters.

okbot follows a ports-and-adapters architecture (ADR 0001). This crate holds the types every other crate speaks and the traits adapters implement. It performs no I/O.

PortImplemented byUsed by
Channelone crate per chat platformthe runtime
InboundSinkthe runtimechannels, to deliver events
AgentBackendagent CLIs, fallback chainsthe runtime
ConversationStoreSQLite storethe runtime
KnowledgeProviderokbase integrationthe runtime
MemoryStoreokbase integrationthe runtime (chat commands)
TaskStoreokbase integrationthe runtime (chat commands, scheduler)
RendererMarkdown dialect rendererthe runtime
ClockSystemClock, test clockseverything that reads time

§Writing a channel

A platform adapter implements Channel: receive events and hand them to the InboundSink, send rendered replies. Everything else (policy, agents, knowledge) is the runtime’s job.

use std::sync::Arc;
use okbot_core::{
    async_trait, CancellationToken, Channel, ChannelCaps, ChannelError, ChannelId, InboundSink,
    MessageId, RenderedMessage, ReplyTarget, SentRef,
};

struct EchoChannel { id: ChannelId, caps: ChannelCaps }

#[async_trait]
impl Channel for EchoChannel {
    fn id(&self) -> &ChannelId { &self.id }
    fn caps(&self) -> &ChannelCaps { &self.caps }

    async fn run(&self, _sink: Arc<dyn InboundSink>, shutdown: CancellationToken)
        -> Result<(), ChannelError> {
        // Connect to the platform and call `sink.deliver(event)` for each message.
        shutdown.cancelled().await;
        Ok(())
    }

    async fn send(&self, to: &ReplyTarget, message: &RenderedMessage)
        -> Result<SentRef, ChannelError> {
        println!("{}", message.text);
        Ok(SentRef { target: to.clone(), message_id: MessageId::new("1") })
    }
}

let channel = EchoChannel { id: "echo:demo".parse().unwrap(), caps: ChannelCaps::basic() };
assert_eq!(channel.id().to_string(), "echo:demo");

Structs§

AgentCaps
What an agent backend can do natively. Missing capabilities are emulated or the backend is skipped.
AgentReply
The result of a successful turn.
AgentRunRecord
One agent run, for the audit table.
AgentTurn
One agent turn.
CancellationToken
Re-exported so adapters use the same cancellation type as the runtime. A token which can be used to signal a cancellation request to one or more tasks.
ChannelCaps
What a channel can do. The runtime adapts its behaviour to these values.
ChannelId
One configured instance of a chat platform, written platform:instance (zalo:shop).
CommandInfo
A command for the platform’s command menu (/ on Discord and Telegram).
CommandParam
A parameter of a CommandInfo.
ConversationKey
Identifies one conversation. Messages with the same key are handled in order and share history.
Fire
One firing of a task: the task id and its planned time identify it.
Form
A small form (a Discord modal: up to five text fields).
FormField
One text field of a Form.
InboundEvent
A message received from a platform, normalized by its channel adapter.
KnowledgeContext
Knowledge placed in the system prompt.
McpServer
An MCP server the agent may call during a run.
MemoryEntry
A stored note.
MemoryNote
A note to save.
MessageId
A message id as the platform reports it.
NewMessage
A message to store.
NewTask
A task to create.
OutboundMessage
A reply in canonical Markdown, before rendering for a platform.
Person
Several platform accounts of one human, linked by the operator.
ProgressFn
Receives AgentProgress; called from the backend’s output reader, so keep it quick.
Prompt
A message with buttons, shown in one conversation.
PromptAnswer
Someone pressed a button (and filled in its form).
PromptButton
A button under the prompt message. With a Form, pressing it opens the form and the answer carries the values.
Redactor
Replaces known secret values in text (log lines, error messages) with [REDACTED].
RenderedMessage
One platform message, already in the platform’s dialect and within its length limit.
ReplyTarget
Where a reply goes.
Requester
Who is asking, which decides what knowledge and memory is visible.
Resume
A native session to continue.
RoleGrant
A role given to an account for a limited time (okbot role grant, /grant).
RunGrant
Access to knowledge tools for one agent run. Dropping it revokes the access.
RunId
The id of one agent run, used in logs and the audit table.
RunInfo
What a run needs from the knowledge tools.
Secret
A secret value that never shows up in Debug output or logs.
SentRef
A message the bot sent, for later edits.
SinkClosed
The runtime stopped accepting events (it is shutting down).
StoredMessage
A stored message.
SystemClock
The system clock.
Task
A stored task.
TaskChange
Changes to a task; None leaves a field as it is.
TokenUsage
Token accounting, when the backend reports it.
ToolCallRecord
One call of an [[mcp]] tool, by an agent or a chat command. Arguments and results are not kept: they may hold secrets.
Usage
What one person used over a period.
UserId
A user id as the platform reports it, unique within one ChannelId.
UserRef
Who wrote a message.
WebhookRequest
An HTTP request delivered to a webhook.
WebhookResponse
The response to a webhook request.

Enums§

AgentError
Why a turn failed.
AgentProgress
Progress while an agent works.
Attachment
Media attached to a message. Platforms that deliver media do so by URL.
ButtonStyle
What a button looks like.
ChannelError
An error from a channel adapter.
FieldStyle
How much text a form field takes.
FireState
Where one firing of a task is (design §5.6).
IdError
An invalid identifier.
KnowledgeError
A knowledge failure.
LengthUnit
How a platform counts message length.
MarkdownDialect
The Markdown flavour a platform displays.
MemoryError
A memory operation failed.
MemoryScope
Who a note is for.
MessageRole
Who wrote a stored message.
NotifyTo
One destination of a [[notify]] target, written as text in okbot.toml.
Repeat
When a task fires again, written daily 08:00, weekdays 08:00, weekly mon,fri 09:00, monthly 1 09:00 or every 3h.
StoreError
A storage failure.
TaskError
A task operation failed.
TaskKind
What a task does when it fires.
TaskStatus
Where a task is in its life.
ToolDecision
What happened to a tool call (ADR 0011).
ToolPolicy
Which tools an agent may use in a room (design §4.4). No policy grants a shell or file access.

Constants§

MAX_BUTTONS
Limits every channel can honour (Discord’s are the tightest).
MAX_FIELDS
Fields per form.
PAIRING_MAX_FAILURES
Wrong pairing codes tolerated before pending codes are cancelled.

Traits§

AgentBackend
Runs agent turns (design §4.1).
Channel
A chat platform adapter (design §3.2).
Clock
A source of the current time, replaceable in tests.
ConversationStore
Stores conversations, deduplication marks and the audit trail (design §6.1).
InboundSink
Receives normalized events from channels. Implemented by the runtime.
KnowledgeProvider
The bot’s knowledge and memory (design §5).
MemoryStore
Saves, lists and forgets notes, always within the requester’s visibility.
Renderer
Turns canonical Markdown into platform messages: the platform’s dialect, each part within its length limit.
TaskStore
Creates, lists and changes tasks, always within the requester’s visibility.
WebhookHandler
Receives webhook requests for one channel.

Functions§

format_time
Formats ts as an RFC 3339 instant with the offset of tz (2026-10-14T08:00:00+07:00).
parse_time
Reads a time written by a user or an agent: an RFC 3339 instant (2026-10-14T08:00:00+07:00), a local date-time in tz (2026-10-14T08:00, 2026-10-14 08:00) or a local date (09:00).
person_key
The key a person’s usage and audit entries are stored under: person:<id> for linked accounts ([people], or the owner of a personal bot), else the account platform:instance/user-id.
sort_tasks
Sorts tasks for display: active first, then by the earliest of next firing and due time, then by creation.

Type Aliases§

BoxError
A boxed error from an adapter, kept as the source of port errors.

Attribute Macros§

async_trait
Re-exported so adapters implement the async traits with the same macro version.