Skip to main content

Crate cortex_sdk

Crate cortex_sdk 

Source
Expand description

§Cortex SDK

The official Rust SDK for Cortex’s trusted native plugin boundary.

This crate defines the public plugin surface with zero dependency on Cortex internals. The runtime loads trusted native plugins through a stable C-compatible ABI and bridges these traits to its own turn runtime, command surface, and transport layer.

Process-isolated JSON plugins do not need this crate. They are defined through manifest.toml plus a child-process command. Use cortex-sdk when you are building a trusted in-process native plugin that exports cortex_plugin_init.

§Architecture

 ┌──────────────┐     dlopen      ┌──────────────────┐
 │ cortex-runtime│ ──────────────▶ │  your plugin.so  │
 │   (daemon)    │                 │  cortex-sdk only  │
 └──────┬───────┘   FFI call      └────────┬─────────┘
        │        cortex_plugin_init()         │
        ▼                                    ▼
   ToolRegistry  ◀─── register ───  MultiToolPlugin
                                    ├─ plugin_info()
                                    └─ create_tools()
                                        ├─ Tool A
                                        └─ Tool B

Plugins are compiled as cdylib shared libraries. The runtime calls cortex_plugin_init, receives a C-compatible function table, then asks that table for plugin metadata, tool descriptors, and tool execution results. Rust trait objects stay inside the plugin; they never cross the dynamic-library boundary.

The SDK now exposes a runtime-aware execution surface as well:

  • InvocationContext gives tools stable metadata such as session id, canonical actor, transport/source, and foreground/background scope
  • ToolRuntime lets tools emit progress updates and observer text back to the parent turn
  • ToolCapabilities lets tools declare whether they emit runtime signals and whether they are background-safe
  • Attachment and ToolResult::with_media let tools return structured image, audio, video, or file outputs without depending on Cortex internals

§Quick Start

Cargo.toml:

[lib]
crate-type = ["cdylib"]

[dependencies]
cortex-sdk = "1.2"
serde_json = "1"

src/lib.rs:

use cortex_sdk::prelude::*;

// 1. Define the plugin entry point.
#[derive(Default)]
struct MyPlugin;

impl MultiToolPlugin for MyPlugin {
    fn plugin_info(&self) -> PluginInfo {
        PluginInfo {
            name: "my-plugin".into(),
            version: env!("CARGO_PKG_VERSION").into(),
            description: "My custom tools for Cortex".into(),
        }
    }

    fn create_tools(&self) -> Vec<Box<dyn Tool>> {
        vec![Box::new(WordCountTool)]
    }
}

// 2. Implement one or more tools.
struct WordCountTool;

impl Tool for WordCountTool {
    fn name(&self) -> &'static str { "word_count" }

    fn description(&self) -> &'static str {
        "Count words in a text string. Use when the user asks for word \
         counts, statistics, or text length metrics."
    }

    fn input_schema(&self) -> serde_json::Value {
        serde_json::json!({
            "type": "object",
            "properties": {
                "text": {
                    "type": "string",
                    "description": "The text to count words in"
                }
            },
            "required": ["text"]
        })
    }

    fn execute(&self, input: serde_json::Value) -> Result<ToolResult, ToolError> {
        let text = input["text"]
            .as_str()
            .ok_or_else(|| ToolError::InvalidInput("missing 'text' field".into()))?;
        let count = text.split_whitespace().count();
        Ok(ToolResult::success(format!("{count} words")))
    }
}

// 3. Export the FFI entry point.
cortex_sdk::export_plugin!(MyPlugin);

Tools that need runtime context can override Tool::execute_with_runtime instead of only Tool::execute.

§Build & Install

cargo build --release
cortex plugin install ./my-plugin/

If my-plugin/manifest.toml declares [native].library = "lib/libmy_plugin.so" (or .dylib on macOS), Cortex copies the built library from target/release/ into the installed plugin’s lib/ directory automatically when you install from a local folder.

For versioned distribution:

cargo build --release
cortex plugin pack ./my-plugin
cortex plugin install ./my-plugin-v0.1.0-linux-amd64.cpx
cortex restart

§Plugin Lifecycle

  1. Loaddlopen at daemon startup
  2. Create — runtime calls export_plugin!-generated stable ABI init
  3. RegisterMultiToolPlugin::create_tools is called once; each Tool is registered in the global tool registry
  4. Execute — the LLM invokes tools by name during turns; the runtime calls Tool::execute with JSON parameters
  5. Retain — the library handle is held for the daemon’s lifetime; Drop runs only at shutdown

§Tool Design Guidelines

  • name: lowercase with underscores (word_count, not WordCount). Must be unique across all tools in the registry.
  • description: written for the LLM — explain what the tool does, when to use it, and when not to use it. The LLM reads this to decide whether to call the tool.
  • input_schema: a JSON Schema object describing the parameters. The LLM generates JSON matching this schema.
  • execute: receives the LLM-generated JSON. Return ToolResult::success for normal output or ToolResult::error for recoverable errors the LLM should see. Return ToolError only for unrecoverable failures (invalid input, missing deps).
  • Media output: attach files with ToolResult::with_media. Cortex delivers attachments through the active transport; plugins should not call channel-specific APIs directly.
  • execute_with_runtime: use this when the tool needs invocation metadata or wants to emit progress / observer updates during execution.
  • timeout_secs: optional per-tool timeout override. If None, the global [turn].tool_timeout_secs applies.

Re-exports§

pub use serde_json;

Modules§

prelude
Convenience re-exports for plugin development.

Macros§

export_plugin
Generate the stable native ABI entry point for a MultiToolPlugin.

Structs§

Attachment
Stable multimedia attachment DTO exposed to plugins.
CortexBuffer
Native ABI-owned byte buffer.
CortexHostApi
Host table supplied to a native plugin during initialization.
CortexPluginApi
Function table exported by a native plugin.
InvocationContext
Stable runtime metadata exposed to plugin tools during execution.
PluginInfo
Plugin metadata returned to the runtime at load time.
ToolCapabilities
Declarative hints about how a tool participates in the runtime.
ToolResult
Result of a tool execution returned to the LLM.

Enums§

ExecutionScope
Whether a tool invocation belongs to a user-visible foreground turn or a background maintenance execution.
ToolError
Error from tool execution.

Constants§

NATIVE_ABI_VERSION
Stable native ABI version for trusted in-process plugins.
SDK_VERSION
Version of the SDK crate used by native plugin builds.

Traits§

MultiToolPlugin
A plugin that provides multiple tools from a single shared library.
Tool
A tool that the LLM can invoke during conversation.
ToolRuntime
Runtime bridge presented to tools during execution.

Functions§

cortex_buffer_free
Free a buffer allocated by this SDK.