Skip to main content

walrus_runtime/
hook.rs

1//! Hook trait — stateful runtime backend.
2//!
3//! Hook is the single abstraction that Runtime delegates all backend concerns
4//! to: model access, tool dispatch, prompt enrichment, and event observation.
5//! Implementations own the concrete backends (model provider, memory, MCP,
6//! tool registry, skill registry).
7
8use anyhow::Result;
9use std::future::Future;
10use wcore::AgentConfig;
11use wcore::AgentEvent;
12use wcore::model::{Model, Tool};
13
14/// Stateful runtime backend.
15///
16/// Owns the model provider, tool registry, skill registry, MCP bridge, and
17/// any other backend state. Runtime holds `Arc<H>` and delegates through
18/// these methods.
19pub trait Hook: Send + Sync {
20    /// The model provider for this hook.
21    type Model: Model + Send + Sync;
22
23    /// Access the model provider.
24    fn model(&self) -> &Self::Model;
25
26    /// Return tool schemas available to the named agent.
27    fn tools(&self, agent: &str) -> Vec<Tool>;
28
29    /// Dispatch tool calls for the named agent.
30    ///
31    /// Each entry in `calls` is `(method_name, params_json)`. Returns one
32    /// result per call in the same order.
33    fn dispatch(
34        &self,
35        agent: &str,
36        calls: &[(&str, &str)],
37    ) -> impl Future<Output = Vec<Result<String>>> + Send;
38
39    /// Build an enriched system prompt for the given agent config.
40    ///
41    /// Default implementation returns the config's system prompt unchanged.
42    /// Override to inject skills, MCP context, or other prompt augmentation.
43    fn enrich_prompt(&self, config: &AgentConfig) -> String {
44        config.system_prompt.clone()
45    }
46
47    /// Called when an agent emits an event during execution.
48    ///
49    /// Default is a no-op.
50    fn on_event(&self, _event: &AgentEvent) {}
51}
52
53impl Hook for () {
54    type Model = ();
55
56    fn model(&self) -> &() {
57        &()
58    }
59
60    fn tools(&self, _agent: &str) -> Vec<Tool> {
61        vec![]
62    }
63
64    fn dispatch(
65        &self,
66        _agent: &str,
67        calls: &[(&str, &str)],
68    ) -> impl Future<Output = Vec<Result<String>>> + Send {
69        let len = calls.len();
70        async move { (0..len).map(|_| Ok(String::new())).collect() }
71    }
72}