Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Migrating from Tirea

Awaken is a ground-up rewrite of tirea, not an incremental upgrade. This guide maps tirea 0.5 concepts to their awaken equivalents for developers porting existing agents.

The tirea 0.5 source is archived on the tirea-0.5 branch.

Crate Mapping

tirea 0.5awakenNotes
tirea-stateawaken-contractState engine merged into contract crate
tirea-state-deriveRemoved; use StateKey trait directly
tirea-contractawaken-contractMerged types + traits into one crate
tirea-agentosawaken-runtimeRenamed; same role (execution engine)
tirea-store-adaptersawaken-storesRenamed
tirea-agentos-serverawaken-serverRenamed; protocols now inline
tirea-protocol-ai-sdk-v6awaken-server::protocols::ai_sdk_v6Merged into server crate
tirea-protocol-ag-uiawaken-server::protocols::ag_uiMerged into server crate
tirea-protocol-acpawaken-server::protocols::acpMerged into server crate
tirea-extension-permissionawaken-ext-permissionRenamed
tirea-extension-observabilityawaken-ext-observabilityRenamed
tirea-extension-skillsawaken-ext-skillsRenamed
tirea-extension-mcpawaken-ext-mcpRenamed
tirea-extension-handoffawaken-runtime::extensions::handoffMerged into runtime
tirea-extension-a2uiawaken-ext-generative-uiRenamed
tirea (facade)awakenRenamed

Key structural change: tirea had 16 crates; awaken has 13. Protocol crates were merged into awaken-server, the state derive macro was removed, and tirea-state + tirea-contract were unified into awaken-contract.

State Model

tirea used a derive-macro-based state system. Awaken uses a trait-based approach.

// tirea 0.5
#[derive(StateSlot)]
#[state(key = "my_plugin.counter", scope = "run")]
struct Counter(u32);

// awaken
use awaken::prelude::*;

pub struct Counter;

impl StateKey for Counter {
    const KEY: &'static str = "my_plugin.counter";
    const MERGE: MergeStrategy = MergeStrategy::Exclusive;
    type Value = u32;
    type Update = u32;

    fn apply(value: &mut u32, update: u32) {
        *value = update;
    }
}
tirea conceptawaken equivalent
StateSlot deriveStateKey trait impl
ScopeDomain::RunKeyScope::Run (default)
ScopeDomain::ThreadKeyScope::Thread
ScopeDomain::GlobalRemoved (use KeyScope::Thread + ProfileStore)
state.get::<T>()snapshot.get::<T>() (via ctx.state::<T>() in hooks)
state.set(value)cmd.update::<T>(value) (via StateCommand)
Mutable state accessImmutable snapshots + StateCommand returns

Key change: State is never mutated directly. Hooks read from immutable snapshots and return StateCommand with updates. The runtime applies all updates atomically after the gather phase.

Action System

tirea used typed action enums per phase. Awaken uses ScheduledActionSpec with handlers.

// tirea 0.5
BeforeInferenceAction::AddContextMessage(
    ContextMessage::system("key", "content")
)

// awaken
use awaken::prelude::*;

let mut cmd = StateCommand::new();
cmd.schedule_action::<AddContextMessage>(
    ContextMessage::system("key", "content"),
)?;
tirea actionawaken actionNotes
BeforeInferenceAction::AddContextMessageAddContextMessageSame semantics
BeforeInferenceAction::SetInferenceOverrideSetInferenceOverrideSame semantics
BeforeInferenceAction::ExcludeToolExcludeToolSame semantics
BeforeToolExecuteAction::BlockToolInterceptAction with Block payloadUnified intercept
BeforeToolExecuteAction::SuspendToolInterceptAction with Suspend payloadUnified intercept
AfterToolExecuteAction::AddMessageAddContextMessageGeneralized

See Scheduled Actions for the full list.

Plugin Trait

// tirea 0.5
impl Extension for MyPlugin {
    fn name(&self) -> &str { "my_plugin" }
    fn register(&self, ctx: &mut ExtensionContext) -> Result<()> {
        ctx.add_hook(Phase::BeforeInference, MyHook);
        Ok(())
    }
}

// awaken
impl Plugin for MyPlugin {
    fn descriptor(&self) -> PluginDescriptor {
        PluginDescriptor { name: "my_plugin" }
    }
    fn register(&self, r: &mut PluginRegistrar) -> Result<(), StateError> {
        r.register_phase_hook("my_plugin", Phase::BeforeInference, MyHook)?;
        r.register_key::<MyState>(StateKeyOptions::default())?;
        Ok(())
    }
}
tireaawakenNotes
Extension traitPlugin traitRenamed
ExtensionContextPluginRegistrarMore structured; explicit key/tool/hook registration
ctx.add_hook()r.register_phase_hook()Requires plugin_id parameter
r.register_key::<T>()New: state keys must be declared at registration
r.register_tool()New: plugin-scoped tools
r.register_scheduled_action::<A, _>(handler)New: custom action handlers

Tool Trait

// tirea 0.5
#[async_trait]
impl TypedTool for MyTool {
    type Args = MyArgs;
    async fn call(&self, args: Self::Args, ctx: ToolContext) -> ToolOutput {
        ToolOutput::success(json!({"result": 42}))
    }
}

// awaken
#[async_trait]
impl Tool for MyTool {
    fn descriptor(&self) -> ToolDescriptor { ... }
    async fn execute(&self, args: Value, ctx: &ToolCallContext) -> Result<ToolOutput, ToolError> {
        Ok(ToolResult::success("my_tool", json!({"result": 42})).into())
    }
}
tireaawakenNotes
TypedTool with type ArgsTool with Value argsNo generic Args; validate in execute()
ToolOutput (direct return)ToolOutput (result + optional StateCommand)New: tools can schedule actions
ToolContextToolCallContextRenamed; adds state(), profile_access()

Runtime Builder

// tirea 0.5
let runtime = AgentOsBuilder::new()
    .agent(agent_spec)
    .tool("search", SearchTool)
    .extension(PermissionExtension::new(rules))
    .build()?;

// awaken
let runtime = AgentRuntimeBuilder::new()
    .with_agent_spec(agent_spec)
    .with_tool("search", Arc::new(SearchTool))
    .with_plugin("permissions", Arc::new(PermissionPlugin::new(rules)))
    .build()?;
tireaawakenNotes
AgentOsBuilderAgentRuntimeBuilderRenamed
.agent(spec).with_agent_spec(spec)Consistent with_ prefix
.tool(id, impl).with_tool(id, Arc<dyn Tool>)Explicit Arc wrapping
.extension(ext).with_plugin(id, Arc<dyn Plugin>)Renamed; requires ID
.build().build()Same

Concepts Removed

The following tirea concepts have no awaken equivalent:

tirea conceptReason removed
StateSlot derive macroTrait impl is simpler and doesn’t require proc-macro
Global scopeThread scope + ProfileStore covers this
RuntimeEffectReplaced by StateCommand effects
EffectLog / ScheduledActionLogReplaced by tracing
ConfigStore / ConfigSlotReplaced by AgentSpec sections
AgentProfileMerged into AgentSpec
ExtensionContext live activationReplaced by static plugin_ids on AgentSpec

Concepts Added

awaken conceptDescription
PluginRegistrarStructured registration (keys, tools, hooks, actions)
ToolOutput with StateCommandTools can schedule actions as side-effects
ToolInterceptActionUnified Block/Suspend/SetResult pipeline
CircuitBreakerPer-model LLM failure protection
MailboxDurable job queue with lease-based claim
EventReplayBufferSSE reconnection with frame replay
DeferredToolsPluginLazy tool loading with probability model
ProfileStoreCross-session persistent state

Quick Checklist

  • Replace tirea dependency with awaken in Cargo.toml
  • Replace use tirea::* with use awaken::prelude::*
  • Convert #[derive(StateSlot)] to impl StateKey for ...
  • Convert Extension impls to Plugin impls with PluginRegistrar
  • Convert TypedTool impls to Tool impls
  • Replace action enum variants with cmd.schedule_action::<ActionType>(...)
  • Replace AgentOsBuilder with AgentRuntimeBuilder
  • Update store imports: tirea_store_adaptersawaken_stores
  • Update server imports: protocol crates → awaken_server::protocols::*