# Detailed Architecture

This page is the first stop before making non-trivial changes in KylinBot. It
summarizes the current architecture, the intended crate boundaries, and the
places where behavior crosses security, runtime, provider, channel, tool, and
memory layers.

## Current Shape

KylinBot is a Rust workspace moving toward a microkernel architecture. The
stable direction is trait-driven: public contracts live in `kylinbot-api`,
runtime orchestration lives in `kylinbot-runtime`, concrete integrations live in
edge crates, and support crates provide persistence, config, telemetry, plugin,
and hardware services.

The top-level `kylinbot` crate is still important. It owns the CLI binary,
command enums, feature wiring, compatibility modules, and some feature-gated
runtime paths while the workspace split continues. Do not assume all behavior
has already moved from `src/` to `crates/`.

```mermaid
flowchart TB
    CLI["kylinbot binary<br/>src/main.rs"]
    LIB["top-level library<br/>src/lib.rs"]
    API["kylinbot-api<br/>traits and shared types"]
    CFG["kylinbot-config<br/>schema, loading, secrets"]
    RT["kylinbot-runtime<br/>agent loop, policy, cron, SOP, skills"]
    PR["kylinbot-providers<br/>LLM clients, routing, fallback"]
    CH["kylinbot-channels<br/>chat, webhook, ACP, voice"]
    TL["kylinbot-tools<br/>agent-callable tools"]
    MEM["kylinbot-memory<br/>conversation memory and retrieval"]
    GW["kylinbot-gateway<br/>HTTP, WebSocket, dashboard"]
    PLG["kylinbot-plugins<br/>WASM and dynamic plugin loading"]
    HW["kylinbot-hardware<br/>USB, GPIO, serial, boards"]
    INF["kylinbot-infra<br/>shared infrastructure"]

    CLI --> LIB
    CLI --> CFG
    CLI --> RT
    CLI --> GW
    RT --> API
    PR --> API
    CH --> API
    TL --> API
    MEM --> API
    RT --> CFG
    RT --> PR
    RT --> CH
    RT --> TL
    RT --> MEM
    RT --> INF
    GW --> RT
    RT --> PLG
    RT --> HW
```

## Architectural Rules

- `kylinbot-api` defines contracts. It should not depend on concrete providers,
  channels, tools, runtime implementations, or UI surfaces.
- `kylinbot-runtime` orchestrates policy and state. It may compose providers,
  channels, tools, memory, skills, hooks, cron, SOP, and observability, but new
  platform integrations should usually live outside the runtime.
- `kylinbot-providers`, `kylinbot-channels`, and `kylinbot-tools` are edge
  crates. They talk to external systems and implement traits from
  `kylinbot-api`.
- `kylinbot-config` is the source of truth for config schema and validation.
  Do not add config keys without a concrete use case and generated/reference
  documentation updates.
- Security policy belongs in the runtime security layer. Edge crates may perform
  local validation, but they must not bypass runtime policy checks for tool
  execution, workspace boundaries, pairing, IAM, or autonomy.
- User-facing CLI output, tool descriptions, and onboarding text must be
  localized through Fluent. Logs, tracing events, error keys, and panic text
  stay in English.

## Main Runtime Flow

The normal user-message path is:

1. A channel, gateway route, ACP client, or CLI command receives an external
   event.
2. The adapter normalizes the event and enforces early pairing, deduplication,
   and allowed-user checks where applicable.
3. The runtime loads conversation context and memory.
4. The provider receives the prompt, tool specs, and history.
5. Provider streaming yields text deltas and optional tool calls.
6. Every tool call is validated by runtime security policy.
7. Approved tool calls are dispatched to registered `Tool` implementations.
8. Tool results and receipts are persisted.
9. The provider resumes with tool results and emits final text.
10. The originating channel or gateway sends the final response.

See also [Request lifecycle](./request-lifecycle.md) for the sequence diagrams.

## Core Contracts

The public extension traits are in `crates/kylinbot-api/src/`:

| Trait | File | Responsibility |
|---|---|---|
| `Provider` | `provider.rs` | Model chat, streaming, native tool capability, provider defaults |
| `Channel` | `channel.rs` | Inbound/outbound messaging, draft updates, operator approval paths |
| `Tool` | `tool.rs` | Agent-callable capability specs and invocation |
| `Memory` | `memory_traits.rs` | Conversation and fact persistence backends |
| `Observer` | `observability_traits.rs` | Runtime telemetry backends |
| `RuntimeAdapter` | `runtime_traits.rs` | Alternative execution environments |
| `Peripheral` | `peripherals_traits.rs` | Hardware boards exposing capabilities |
| `Vad` | `vad.rs` | Voice activity detection |

When adding a new implementation, start from the trait, then find the local
factory or registry that wires concrete implementations into the runtime.

## Crate Responsibilities

### Top-level `kylinbot`

`src/main.rs` is the CLI entrypoint. `src/lib.rs` exposes command enums and
feature-gated modules for the binary and compatibility paths. This crate owns
command routing, feature wiring, schema export hooks, and CLI-facing behavior.

Because the microkernel split is still in progress, some modules exist both in
top-level `src/` and under `crates/kylinbot-runtime/src/`. Before moving code,
check call sites and feature gates from both locations.

### `kylinbot-runtime`

The runtime is the orchestration layer:

- `agent/` builds prompts, loads memory, streams providers, handles tool calls,
  dispatches tools, records receipts, and manages channel handles.
- `security/` owns autonomy policy, sandbox detection, IAM, pairing, OTP,
  emergency stop, prompt guard, secrets handling, and workspace boundaries.
- `tools/` contains runtime-owned tools such as cron, SOP, scheduling, skill,
  model switching, shell, and security operations.
- `skills/`, `skillforge/`, and `sop/` convert local operational knowledge into
  prompt context and callable tools.
- `cron/`, `routines/`, `heartbeat/`, and `service/` handle background and
  daemonized operation.
- `observability/`, `hooks/`, and `health/` report runtime state and events.

Changes here are high-risk when they touch tool execution, policy decisions,
approval flows, workspace access, daemon behavior, or long-running background
tasks.

### `kylinbot-providers`

Provider implementations translate the unified `Provider` contract into
provider-specific HTTP, OAuth, streaming, and tool-call formats.

Important modules:

- `compatible.rs` handles OpenAI-compatible endpoints shared by many providers.
- `router.rs` routes by task hint.
- `reliable.rs` implements fallback chains.
- `streaming` logic is provider-specific or in shared compatible parsing code.
- `auth/` contains OAuth and token helpers.

Provider changes must preserve streaming semantics, tool-call normalization,
timeout/error behavior, and fallback compatibility.

### `kylinbot-channels`

Channels adapt external messaging systems into runtime events and outbound
responses. The `orchestrator/` module handles lifecycle, routing, media
pipeline, and ACP server behavior.

Channel implementations should keep platform-specific details at the edge:
payload decoding, retries, deduplication, rate limits, draft updates, and
platform media handling. Runtime policy still owns tool approval and access
control decisions after a message reaches the agent loop.

### `kylinbot-tools`

Tools are model-callable capabilities such as browser, HTTP, file, memory,
cloud, MCP, image, search, workspace, and integration tools. Tool
implementations must return structured results and be explicit about side
effects.

Tools that read or mutate local state, execute commands, access credentials, or
call networks need particular care. The runtime security layer must have enough
metadata to classify and enforce the call.

### `kylinbot-config`

Config owns the schema, typed values, comments, secrets, migration, and
workspace resolution. CLI, gateway, onboarding, and runtime code should use the
shared config APIs rather than parsing TOML independently.

### `kylinbot-memory`

Memory persists conversations, facts, embeddings, and retrieval state. Runtime
code composes memory into prompt context, while this crate owns backend-specific
storage behavior.

### `kylinbot-gateway`

Gateway exposes runtime behavior over HTTP, WebSocket, dashboard assets, and
webhooks. Public binding, pairing, authentication, and streaming responses are
security-sensitive.

### `kylinbot-plugins`

Plugins provide dynamic extension. The stable design direction is that dynamic
plugins expose capabilities behind the same contracts used by built-in
providers, tools, channels, or runtime adapters.

### `kylinbot-hardware`

Hardware code discovers devices and exposes peripherals over USB, serial, GPIO,
I2C, and SPI. Hardware-facing tools still need normal runtime policy and
receipts when called by the agent.

## Extension Workflows

### Add a provider

1. Implement `Provider` from `kylinbot-api`.
2. Reuse `compatible.rs` for OpenAI-compatible APIs when possible.
3. Register the provider in the provider factory.
4. Add config/schema/documentation for concrete user-facing settings.
5. Add tests for factory resolution, default model behavior, streaming, and tool
   calling if supported.

### Add a channel

1. Implement `Channel`.
2. Keep platform authentication, webhook/polling details, and payload conversion
   in the channel crate.
3. Wire it into the channel factory and feature flags.
4. Document required config and pairing behavior.
5. Test inbound normalization, outbound send/update behavior, and authorization
   checks.

### Add a tool

1. Implement `Tool` with a clear schema and localized user-facing description.
2. Register it in the correct registry or factory.
3. Classify side effects and ensure security policy can gate it.
4. Add focused tests for argument validation, success, failure, and denied paths.
5. Record receipts for meaningful side effects.

### Add config

1. Add the typed schema field in `kylinbot-config`.
2. Add validation and migration/default behavior.
3. Update generated/reference docs as required by the config tooling.
4. Update onboarding or CLI code only when the setting is user-facing.

## High-Risk Boundaries

Treat these as high-risk until proven otherwise:

- `crates/kylinbot-runtime/src/security/**`
- tool dispatch, tool receipts, and approval flow
- `crates/kylinbot-tools/src/**` tools with file, shell, browser, cloud, memory,
  credential, or network effects
- `crates/kylinbot-gateway/src/**` and webhook authentication
- channel pairing, IAM, allowed users, and webhook signature verification
- provider streaming and tool-call parsing
- config schema migrations and secret handling
- `.github/workflows/**`, release scripts, and install/bootstrap scripts

For high-risk changes, read adjacent tests and docs before editing, add or
update focused tests, and document behavior, side effects, and rollback notes in
the PR.

## Start-of-Task Checklist

Before starting a new task:

1. Read this document.
2. Read [Architecture overview](./overview.md) and the relevant focused doc:
   request lifecycle, crates, providers, channels, tools, security, gateway, or
   hardware.
3. Locate the owning crate and factory/registry before editing.
4. Classify risk using `AGENTS.md`.
5. Inspect adjacent tests and feature gates.
6. Keep the patch to one concern.
7. Run validation appropriate to the risk tier.

## Validation Guide

- Docs-only: run the repository markdown and link checks when available.
- Rust code: run `cargo fmt --all -- --check`, `cargo clippy --all-targets -- -D warnings`,
  and `cargo test` or a narrower justified subset while iterating.
- Full pre-PR validation: run `./dev/ci.sh all`.
- Bootstrap scripts: run `bash -n install.sh` if touched.

