Skip to main content

Runtime

Struct Runtime 

Source
pub struct Runtime {
    pub state: Arc<StateStore>,
    pub tools: Arc<RwLock<HashMap<String, ToolSchema>>>,
    pub policies: Arc<RwLock<PolicyEngine>>,
    pub log: Arc<Mutex<EventLog>>,
    pub rate_limiter: Arc<RateLimiter>,
    pub result_cache: Arc<ResultCache>,
    pub registry: Arc<ToolRegistry>,
    /* private fields */
}
Expand description

Common Agent Runtime — deterministic execution layer.

Lock ordering discipline (never hold multiple simultaneously, never hold sync locks across .await):

  1. capabilities (RwLock, read-only during execution)
  2. tools (RwLock, read-only during execution)
  3. policies (RwLock, read-only during execution)
  4. cost_budget (RwLock, read-only during execution)
  5. log (TokioMutex, acquired/released per event)
  6. tool_executor (TokioMutex, clone Arc and drop before await)
  7. idempotency_cache (TokioMutex, acquired/released per check)

StateStore uses parking_lot::Mutex (sync) — NEVER hold across .await points.

Fields§

§state: Arc<StateStore>§tools: Arc<RwLock<HashMap<String, ToolSchema>>>§policies: Arc<RwLock<PolicyEngine>>§log: Arc<Mutex<EventLog>>§rate_limiter: Arc<RateLimiter>§result_cache: Arc<ResultCache>§registry: Arc<ToolRegistry>

Canonical tool registry (optional — new code should use this).

Implementations§

Source§

impl Runtime

Source

pub fn new() -> Self

Source

pub fn with_shared( state: Arc<StateStore>, log: Arc<TokioMutex<EventLog>>, policies: Arc<TokioRwLock<PolicyEngine>>, ) -> Self

Create a runtime with shared state, event log, and policies. Each runtime gets its own tool set, executor, and idempotency cache.

Source

pub fn with_inference(self, engine: Arc<InferenceEngine>) -> Self

Attach a local inference engine. Registers infer, embed, classify as built-in tools with real implementations.

Source

pub fn with_learning( self, memgine: Arc<TokioMutex<MemgineEngine>>, auto_distill: bool, ) -> Self

Attach a memgine for automatic skill learning after execution. When auto_distill is true, execution traces are automatically distilled into skills and domains are evolved when underperforming.

Source

pub fn with_memgine(self, memgine: Arc<TokioMutex<MemgineEngine>>) -> Self

Attach a memgine with auto-distillation enabled (recommended default).

Source

pub fn with_trajectory_store(self, store: Arc<TrajectoryStore>) -> Self

Attach a trajectory store for persisting execution traces.

Source

pub fn with_executor(self, executor: Arc<dyn ToolExecutor>) -> Self

Source

pub async fn set_executor(&self, executor: Arc<dyn ToolExecutor>)

Set a tool executor for the next execute() call. Used by NAPI bindings where executor varies per call.

Source

pub fn with_event_log(self, log: EventLog) -> Self

Source

pub fn with_replan( self, callback: Arc<dyn ReplanCallback>, config: ReplanConfig, ) -> Self

Attach a replan callback for failure recovery (builder).

Source

pub async fn set_replan_callback(&self, callback: Arc<dyn ReplanCallback>)

Set a replan callback at runtime.

Source

pub async fn set_replan_config(&self, config: ReplanConfig)

Set replan configuration at runtime.

Source

pub async fn register_tool(&self, name: &str)

Register a tool with just a name (backward compatible).

Source

pub async fn register_tool_schema(&self, schema: ToolSchema)

Register a tool with full schema.

Source

pub async fn register_tool_entry(&self, entry: ToolEntry)

Register a tool via the canonical registry. This is the preferred way to register tools — it updates both the registry and the legacy tools HashMap for backward compatibility.

Source

pub async fn register_agent_basics(&self)

Register CAR’s built-in agent utility stdlib.

This is an opt-in convenience layer for common local-file and text tools. Existing runtimes remain unchanged until this is called.

Source

pub async fn tool_schemas(&self) -> Vec<ToolSchema>

Get all registered tool schemas (for model prompt generation).

Source

pub async fn set_cost_budget(&self, budget: CostBudget)

Set a cost budget that limits proposal execution.

Source

pub async fn set_capabilities(&self, caps: CapabilitySet)

Set per-agent capability permissions that restrict tools, state keys, and action count.

Source

pub async fn set_rate_limit( &self, tool: &str, max_calls: u32, interval_secs: f64, )

Set a per-tool rate limit (token bucket).

max_calls tokens are available per interval_secs window. When the bucket is empty, dispatch() applies backpressure by waiting until a token refills.

Source

pub async fn enable_tool_cache(&self, tool: &str, ttl_secs: u64)

Enable cross-proposal result caching for a tool with a TTL in seconds.

Source

pub async fn execute(&self, proposal: &ActionProposal) -> ProposalResult

Execute a proposal with automatic replanning on failure.

If a ReplanCallback is registered and max_replans > 0, the runtime will catch abort failures, roll back state, ask the model for an alternative proposal via the callback, and re-execute. This transforms “execute-and-hope” into “execute-and-recover.”

If no callback is registered or max_replans == 0, behaves identically to a single execute_inner() call (zero overhead, fully backward compatible).

Source

pub async fn execute_with_cancel( &self, proposal: &ActionProposal, cancel: &CancellationToken, ) -> ProposalResult

Execute a proposal with cooperative cancellation.

The runtime checks token.is_cancelled() at each DAG level boundary. When set, every action that hadn’t yet started runs is reported as Skipped with error = "canceled: ..." so callers can distinguish “user pulled the plug” from “earlier abort cascaded.” Actions already in flight continue to completion — tool calls dispatched to user-provided executors can’t be safely interrupted from the engine.

The CAR A2A bridge uses this so tasks/cancel produces a ProposalResult with clean partial state rather than relying on JoinHandle::abort to interrupt mid-await (which leaves no record of which actions actually ran).

FFI exposure: this method is intentionally not surfaced through the NAPI / PyO3 / car-server-core JSON-RPC bindings. Those consumers (Node, Python, WebSocket) don’t currently expose long-running async-task surfaces that need cancellation; the bridge is the lone consumer. When a binding gains a long-running task surface, the path is clear: add a per-binding token registry keyed by some caller-provided id, expose cancelExecution(id) / cancel_execution(id) / proposal.cancel { id }, and have the runtime call execute_with_cancel with the matching token. Skipping that today avoids speculative API surface that bloats bindings without a consumer.

Source

pub async fn plan_and_execute( &self, candidates: &[ActionProposal], planner_config: Option<PlannerConfig>, feedback: Option<&ToolFeedback>, ) -> ProposalResult

Score N candidate proposals, execute the best valid one, fall back to next-best on failure. Combines car-planner scoring with engine execution.

Returns the result from whichever proposal was executed (best or fallback). If all candidates fail verification, returns an error result for the first.

Source

pub async fn save_checkpoint(&self) -> Checkpoint

Save a checkpoint of the current runtime state.

Source

pub async fn save_checkpoint_to_file(&self, path: &str) -> Result<(), String>

Save checkpoint to a JSON file.

Source

pub async fn load_checkpoint_from_file( &self, path: &str, ) -> Result<Checkpoint, String>

Load a checkpoint from a JSON file and restore state.

Source

pub async fn restore_checkpoint(&self, checkpoint: &Checkpoint)

Restore runtime state from a checkpoint.

Source

pub async fn register_subprocess_tool(&self, name: &str, tool: SubprocessTool)

Register a subprocess tool and set up the subprocess executor. If no executor exists, creates a new SubprocessToolExecutor. If one already exists, creates a new SubprocessToolExecutor with the existing executor as fallback.

Trait Implementations§

Source§

impl Default for Runtime

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> ErasedDestructor for T
where T: 'static,