Skip to content

Plugins

Architecture Section

This page is part of the Architecture section. Plugins are the swappable extension layer -- built-in and user-provided plugins follow the exact same shapes.

Plugins are swappable, shape-conforming components. Built-in and user-provided plugins follow the exact same shapes -- the plugin registry auto-discovers both on startup.

Plugin Shape

Every plugin has a top-level Plugin record defined in plugins/types.gleam:

gleam
pub type Plugin {
  Plugin(
    name: String,
    description: String,
    plugin_type: PluginType,
    supervised: Bool,
    start: fn() -> Result(Nil, String),
    stop: fn() -> Nil,
    health: fn() -> Bool,
  )
}

The plugin_type is one of four zero-argument variants:

gleam
pub type PluginType {
  Tool
  Gateway
  Hook
  MemoryProvider
}

Plugin Types

Tools

Things the agent can do. Each tool implements the Tool shape from core/tool/tool.gleam:

gleam
pub type Tool {
  Tool(
    name: String,
    description: String,
    schema: Json,
    handler: fn(String) -> ToolResult,
    parallel_safe: Bool,
  )
}

Built-in tools:

ToolModuleDescription
bashplugins/tools/bash/Shell command execution (sandboxed)
webplugins/tools/web/Web page fetching (SSRF-hardened)
browserplugins/tools/browser/Playwright browser automation (6 actions)
codeplugins/tools/code/Python/Node/Bash code executor
memoryplugins/tools/memory/Memory CRUD (SQLite-backed)
session_searchplugins/tools/session_search/Search past conversations
cronplugins/tools/cron/Cron job management
send_messageplugins/tools/gateways/telegram/Send Telegram messages

Gateways

Channels the agent communicates through. Each gateway implements the Gateway shape from plugins/gateways/types.gleam:

gleam
pub type Gateway {
  Gateway(
    name: String,
    gateway_type: GatewayType,
    start: fn() -> Result(Nil, String),
    stop: fn() -> Result(Nil, String),
    health: fn() -> Result(String, String),
  )
}

Built-in gateways:

  • Telegram -- real Telegram bot using telega's OTP supervision tree with long-polling
  • TUI -- terminal UI for the CLI REPL (planned -- no code yet, see plugins/gateways/tui/README.md)

Hooks

Lifecycle callbacks that fire at specific points in the conversation loop. Hook types are defined in plugins/hooks/types.gleam:

gleam
pub type PreApiCallHook = fn(List(Message), Int) -> List(Message)
pub type PostToolExecutionHook = fn(List(Message), ToolResult) -> List(Message)

Built-in hooks:

  • Context Compressor -- summarizes middle conversation messages when the context window fills up
  • Reflection -- post-turn memory consolidation (nudge engine)
  • Tool Guardrails -- circuit breaker for detecting and interrupting stuck tool loops

Memory Providers

Persistence backends for agent memory. The PluginType variant is MemoryProvider.

Built-in memory providers:

  • File Memory (plugins/memory/file_memory/) -- file-based memory storage under $AGENT_HOME/memories/

Writing a Custom Plugin

Custom Tool

Create a module at ~/.agent/tools/my_tool.gleam:

gleam
import core/tool/tool.{type Tool, type ToolResult, Completed, Tool}
import gleam/json

pub fn tool() -> Tool {
  Tool(
    name: "my_tool",
    description: "Does something useful",
    schema: json.object([]),
    handler: fn(_args_json: String) -> ToolResult {
      Completed("Hello from my_tool!")
    },
    parallel_safe: True,
  )
}

Real built-in tools receive their dependencies as parameters. For example, bash.tool(guardrail: Guardrail) -> Tool accepts a Guardrail behaviour for command safety checking. The registry builder (core/registry/builder.gleam) wires these dependencies at startup.

The plugin registry auto-discovers any .gleam file in ~/.agent/tools/ on startup. Your tool appears in the agent's tool list immediately.

Custom Hook

Same pattern -- create a module in ~/.agent/hooks/ that implements the hook shape. Hooks can be PreApiCallHook (fire before API calls) or PostToolExecutionHook (fire after tool execution).

Custom Gateway

Gateways follow the same pattern in ~/.agent/gateways/. A gateway's job is to translate between the agent's internal message format and an external chat platform. See the built-in Telegram gateway at plugins/gateways/telegram/ as a reference.

Built with Gleam on the BEAM/Erlang VM.