Skip to content

awakenworks/awaken

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

549 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Awaken

English | 中文

CI crates.io awaken crates.io awaken-agent Changelog License MSRV

A Rust agent runtime that serves AI SDK, CopilotKit, A2A, and MCP from the same backend, recovers from mid-stream LLM failures, and treats configuration as the control plane.

awaken is the canonical crate (transferred to this project from @brayniac; see the acknowledgement below). awaken-agent is a thin compatibility republish from when the project shipped under that name. Import path is awaken either way. MSRV: Rust 1.93.

Docs: GitHub Pages · Chinese docs · Changelog

Awaken demo — tool call + LLM streaming

What you get in 0.4

  • Multi-protocol from one backend. A single runtime serves AI SDK v6, AG-UI / CopilotKit, A2A, and MCP. The same /v1/runs powers all of them.
  • Streaming LLM calls survive transient failures. Mid-stream interruptions and idle stalls are detected and recovered through four explicit plans (continue text, replay completed tool calls, restart with a cancelled-tool hint, or whole restart). Retry-After is honored. A StreamCheckpointStore contract extends the same recovery across process restarts. (details)
  • Threads have a parent-child lineage. Sub-agent runs create child threads; deletion is explicit (reject / detach / cascade). Filters and cursors on /v1/threads make hierarchical UIs straightforward.
  • Secrets stay redacted. ProviderSpec.api_key, admin and A2A bearer tokens are wrapped in RedactedStringDebug/Display print ***, the buffer is zeroized on drop, and the JSON wire format is unchanged.
  • Configuration is the control plane. Models, providers, prompts, reminders, permissions, and tool-loading policy live behind /v1/config/* and /v1/capabilities. Apply bursts can be debounced and provider executors are reused across unchanged specs.
  • Type-safe state and tools. Typed StateKeys with merge strategies, generated JSON Schema for TypedTool, atomic batched commits after each phase. unsafe_code = "forbid" workspace-wide.

Mental model

  1. Tools — implement Tool directly, or TypedTool with schemars-generated JSON Schema.
  2. Agents — system prompt, model binding, allowed tools. The LLM orchestrates through natural language; there is no DAG.
  3. State — typed run/thread state plus persistent profile and shared state for cross-thread or cross-agent coordination.
  4. Plugins — lifecycle hooks for permission, observability, context management, skills, MCP, generative UI.

The runtime drives 9 typed phases per round, including a pure ToolGate before tool execution. State mutations are batched and committed atomically.

Quickstart

Prerequisites: Rust 1.93+ and an OpenAI-compatible API key.

[dependencies]
awaken = { version = "0.4.0" }
tokio = { version = "1.51.0", features = ["full"] }
async-trait = "0.1.89"
serde_json = "1.0.149"
export OPENAI_API_KEY=<your-key>

Copy this into src/main.rs and run cargo run:

use std::sync::Arc;
use serde_json::{json, Value};
use async_trait::async_trait;
use awaken::contract::tool::{Tool, ToolDescriptor, ToolResult, ToolOutput, ToolError, ToolCallContext};
use awaken::contract::message::Message;
use awaken::engine::GenaiExecutor;
use awaken::registry_spec::AgentSpec;
use awaken::registry::ModelBinding;
use awaken::{AgentRuntimeBuilder, RunRequest};

struct EchoTool;

#[async_trait]
impl Tool for EchoTool {
    fn descriptor(&self) -> ToolDescriptor {
        ToolDescriptor::new("echo", "Echo", "Echo input back to the caller")
            .with_parameters(json!({
                "type": "object",
                "properties": { "text": { "type": "string" } },
                "required": ["text"]
            }))
    }

    async fn execute(&self, args: Value, _ctx: &ToolCallContext) -> Result<ToolOutput, ToolError> {
        let text = args["text"].as_str().unwrap_or_default();
        Ok(ToolResult::success("echo", json!({ "echoed": text })).into())
    }
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let agent_spec = AgentSpec::new("assistant")
        .with_model_id("gpt-4o-mini")
        .with_system_prompt("You are a helpful assistant. Use the echo tool when asked.")
        .with_max_rounds(5);

    let runtime = AgentRuntimeBuilder::new()
        .with_agent_spec(agent_spec)
        .with_tool("echo", Arc::new(EchoTool))
        .with_provider("openai", Arc::new(GenaiExecutor::new()))
        .with_model_binding("gpt-4o-mini", ModelBinding {
            provider_id: "openai".into(),
            upstream_model: "gpt-4o-mini".into(),
        })
        .build()?;

    let request = RunRequest::new(
        "thread-1",
        vec![Message::user("Say hello using the echo tool")],
    )
    .with_agent_id("assistant");

    // The quickstart only needs the final result. Use run(..., sink) when
    // streaming events to SSE, WebSocket, protocol adapters, or tests.
    let result = runtime.run_to_completion(request).await?;
    println!("response: {}", result.response);
    println!("termination: {:?}", result.termination);

    Ok(())
}

The quickstart path is covered without network access:

cargo test -p awaken --test readme_quickstart

Live provider validation is opt-in so CI does not depend on external model services:

OPENAI_API_KEY=<your-key> cargo test -p awaken --test readme_live_provider -- --ignored

Serve over any protocol

Start the built-in server and connect from React, Next.js, or another agent — no code changes:

use awaken::prelude::*;
use awaken::stores::{InMemoryMailboxStore, InMemoryStore};
use std::sync::Arc;

let store = Arc::new(InMemoryStore::new());
let runtime = Arc::new(runtime);
let mailbox = Arc::new(Mailbox::new(
    runtime.clone(),
    Arc::new(InMemoryMailboxStore::new()),
    store.clone(),
    "default-consumer".into(),
    MailboxConfig::default(),
));

let state = AppState::new(
    runtime.clone(),
    mailbox,
    store,
    runtime.resolver_arc(),
    ServerConfig::default(),
);
serve(state).await?;

Frontend protocols

Protocol Endpoint Frontend
AI SDK v6 POST /v1/ai-sdk/chat React useChat()
AG-UI POST /v1/ag-ui/run CopilotKit <CopilotKit>
A2A POST /v1/a2a/message:send Other agents
MCP POST /v1/mcp JSON-RPC 2.0

The optional admin console reads /v1/capabilities and writes through /v1/config/* to manage agents, models, providers, MCP servers, and plugin config sections. Plugins expose their schema via the same typed PluginConfigKey used at runtime, so saving an agent's permission, reminder, generative-ui, or deferred_tools section publishes a new registry snapshot that takes effect on the next /v1/runs request. OpenAI-compatible providers (including BigModel) use the openai adapter with their own base_url; non-secret extras go in ProviderSpec.adapter_options.

Tuning surface Where it lives
Base prompt AgentSpec.system_prompt
Model and provider routing AgentSpec.model_id + /v1/config/models + /v1/config/providers
System reminders and prompt injection reminder plugin section
Generative UI prompt guidance generative-ui plugin section
Tool policy and context cost permission and deferred_tools plugin sections

React + AI SDK v6:

import { useChat } from "@ai-sdk/react";
import { DefaultChatTransport } from "ai";

const { messages, sendMessage } = useChat({
  transport: new DefaultChatTransport({
    api: "http://localhost:3000/v1/ai-sdk/chat",
  }),
});

Next.js + CopilotKit:

import { CopilotKit } from "@copilotkit/react-core";

<CopilotKit runtimeUrl="http://localhost:3000/v1/ag-ui/run">
  <YourApp />
</CopilotKit>

Managed configuration

Wire a ConfigStore into AppState to manage agents, models, providers, and MCP servers through /v1/config/*. Use the configuration-driven tuning guide to tune providers, model bindings, tools, and plugin sections. The Admin Console in apps/admin-console uses the same API and reads VITE_BACKEND_URL for the server base URL.

Built-in plugins

The facade full feature pulls in the plugins below. Use default-features = false to opt out. awaken-ext-deferred-tools is not re-exported by the facade and is added as a direct dependency.

Plugin What it does Feature flag
Permission Allow/Deny/Ask rules with glob and regex matching on tool name and arguments. Deny beats Allow beats Ask; Ask suspends the run via the mailbox for HITL. permission
Reminder Injects system or conversation-level context messages when a tool call matches a configured pattern. reminder
Observability OpenTelemetry traces and metrics aligned with the GenAI Semantic Conventions; OTLP, file, and in-memory exports. observability
MCP Connects to external MCP servers and registers their tools as native Awaken tools. mcp
Skills Discovers skill packages and injects a catalog before inference so the LLM can activate skills on demand. skills
Generative UI Streams declarative UI components to frontends via A2UI, JSON Render, and OpenUI Lang integrations. generative-ui
Deferred Tools Hides large tool schemas behind a ToolSearch step, then re-defers tools that have been idle for a configurable number of turns using a discounted Beta usage model. direct crate: awaken-ext-deferred-tools

Custom tool interception goes through ToolGateHook via PluginRegistrar::register_tool_gate_hook(). BeforeToolExecute is reserved for execution-time hooks that only run when a tool is actually about to execute.

When this fits

  • You want a Rust backend for AI agents with compile-time guarantees.
  • You need to serve AI SDK, CopilotKit, A2A, and/or MCP from a single backend.
  • Tools need to share state safely during concurrent execution, and runs need auditable history with checkpoints and resume.
  • You're comfortable registering your own tools and providers instead of relying on batteries-included defaults.

When it doesn't

  • You need built-in file/shell/web tools out of the box — consider OpenAI Agents SDK, Dify, or CrewAI.
  • You want a visual workflow builder — consider Dify or LangGraph Studio.
  • You want Python and rapid prototyping — consider LangGraph, AG2, or PydanticAI.
  • You need an LLM-managed memory subsystem where the agent decides what to remember — consider Letta.

Architecture

Awaken is split into three runtime layers. awaken-contract defines the shared contracts: agent specs, model/provider specs, tools, events, transport traits, and the typed state model. awaken-runtime resolves an AgentSpec into ResolvedExecution: local agents become a ResolvedAgent with an ExecutionEnv built from plugins, while endpoint-backed agents run through an ExecutionBackend. It also executes the phase loop and manages active runs plus external control such as cancellation and HITL decisions. awaken-server exposes that same runtime through HTTP routes, SSE replay, mailbox-backed background execution, and protocol adapters for AI SDK v6, AG-UI, A2A, and MCP.

Around those layers sit storage and extensions. awaken-stores provides memory, file, and PostgreSQL persistence for threads and runs; memory, file, and PostgreSQL config stores; memory and SQLite mailbox stores; and memory/file profile stores. awaken-ext-* crates extend the runtime at phase and tool boundaries.

awaken                   Facade crate with feature flags
├─ awaken-contract       Contracts: specs, tools, events, transport, state model
├─ awaken-runtime        Resolver, phase engine, loop runner, runtime control
├─ awaken-server         Routes, mailbox, SSE transport, protocol adapters
├─ awaken-stores         Memory, file, PostgreSQL, and SQLite-backed stores
├─ awaken-tool-pattern   Glob/regex matching used by extensions
└─ awaken-ext-*          Optional runtime extensions

Examples and learning paths

Example What it shows
live_test Basic LLM integration
multi_turn Multi-turn with persistent threads
tool_call_live Tool calling with calculator
ai-sdk-starter React + AI SDK v6 full-stack
copilotkit-starter Next.js + CopilotKit full-stack
openui-chat OpenUI Lang chat frontend
admin-console Config API management UI
export OPENAI_API_KEY=<your-key>
cargo run --package awaken --example multi_turn

cd examples/ai-sdk-starter && npm install && npm run dev

# Terminal 1: starter backend for admin console
AWAKEN_STORAGE_DIR=./target/admin-sessions cargo run -p ai-sdk-starter-agent

# Terminal 2: admin console
npm --prefix apps/admin-console install
npm --prefix apps/admin-console run dev
Goal Start with Then
Build your first agent Get Started Build Agents
See a full-stack app AI SDK starter CopilotKit starter
Manage runtime config Admin Console Configure Agent Behavior
Explore the API Reference docs cargo doc --workspace --no-deps --open
Understand the runtime Architecture Run Lifecycle and Phases
Migrate from tirea Migration guide

Contributing

See CONTRIBUTING.md and DEVELOPMENT.md for setup details.

Good first issues are a great entry point. Quick contribution flow: fork → create a branch → write tests → open a PR.

Areas where contributions are especially welcome:

  • Additional mailbox, config, and storage backends beyond the built-in memory/file/PostgreSQL/SQLite options
  • Built-in tool implementations (file read/write, web search)
  • Token cost tracking and budget enforcement
  • Model fallback/degradation chains

Join the conversation on GitHub Discussions.

Acknowledgement

The awaken crate name on crates.io was generously transferred from @brayniac, who maintained an earlier crate under the same name and offered to hand it over so this project could publish canonically. Versions 0.10.3 of awaken on crates.io belong to that earlier project; this codebase resumes the line that previously shipped as awaken-agent 0.2.x and starts at 0.4.0 to skip past the prior versions. Thank you.

Awaken is also a ground-up rewrite of tirea and is not backwards-compatible with it. The tirea 0.5 codebase remains archived on the tirea-0.5 branch.

License

Dual-licensed under MIT or Apache-2.0.

About

AI agent runtime for Rust — type-safe state, multi-protocol serving, plugin extensibility.

Topics

Resources

License

Unknown and 2 other licenses found

Licenses found

Unknown
LICENSE
Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors