flowcat_core/brain.rs
1// SPDX-License-Identifier: Apache-2.0
2//
3//! The conversation decision-maker seam.
4//!
5//! The embedder implements [`AgentBrain`] over its own engine; flowcat-core
6//! ships a demo brain. The brain owns the system prompt + tool set for the
7//! current state and decides what a tool call means (see DESIGN.md
8//! "Trait contracts").
9//!
10//! [`BrainAction`] and [`ToolDecl`] are defined in [`crate::types`] (the shared
11//! data-type module) and re-exported here, which is their contract location.
12
13use serde_json::Value;
14
15// Re-export so callers can use `crate::brain::{BrainAction, ToolDecl}` as the
16// design lays out, while the type definitions live in `frame`.
17pub use crate::types::{BrainAction, ToolDecl};
18
19/// Drives the conversation: provides the active prompt + tools, interprets tool
20/// calls into [`BrainAction`]s, and reports completion + collected variables.
21///
22/// Synchronous on purpose — the brain is pure decision logic; any I/O it needs
23/// (e.g. the embedder's engine) is done by the implementor before/around these calls.
24pub trait AgentBrain: Send {
25 /// The system prompt for the current conversation state.
26 fn system_prompt(&self) -> String;
27
28 /// Tools available in the current state (transitions + endCall, + later node tools).
29 fn tools(&self) -> Vec<ToolDecl>;
30
31 /// The id of the brain's current conversation node. The pipeline uses this to
32 /// scope the control-plane lookup of the node's MCP/HTTP workflow tools
33 /// (`SessionSource::node_tools` / `tool_call`).
34 fn current_node_id(&self) -> String;
35
36 /// Interpret a tool/function call from the model into a [`BrainAction`].
37 fn on_tool_call(&mut self, name: &str, args: &Value) -> BrainAction;
38
39 /// Whether the conversation has reached a terminal state.
40 fn is_finished(&self) -> bool;
41
42 /// The variables collected so far (folded into the finalize payload).
43 fn collected_vars(&self) -> Value;
44}