Recipe engine
Typed DAG composition with trust propagation, governance gates, and durable execution. Status — scaffolded.
The recipe engine in engine/recipe/ is MAP's typed DAG runner. A recipe is a content-addressed, versioned workflow built from RecipeSteps with explicit data flow, audit checkpoints, and governance gates. The executor propagates a confidence score through the DAG so the institution can reason about the trustworthiness of a composite result.
The recipe engine is scaffolded. The Recipe, RecipeStep, and Executor types are defined and most of the executor logic compiles, but the wiring to a POST /v1/recipe/run daemon endpoint is Phase 1B work. Use direct protocol dispatch in production today.
Core types
pub struct Recipe {
pub id: String, // content-addressed hash
pub version: String,
pub steps: Vec<RecipeStep>, // execution DAG
pub audit_checkpoints: Vec<AuditPoint>,
pub governance_gates: Vec<GovernanceGate>,
}
pub enum RecipeStep {
Protocol {
protocol: String,
operation: String,
payload: serde_json::Value,
depends_on: Vec<String>,
},
Gate {
condition: BoolExpr,
on_true: StepAction,
on_false: StepAction,
},
Audit {
event_type: String,
metadata: serde_json::Value,
},
SubRecipe {
recipe_id: String,
params: serde_json::Value,
},
Parallel {
steps: Vec<RecipeStep>,
},
}StepResult and trust propagation
pub struct StepResult {
pub data: serde_json::Value,
pub metadata: StepMetadata,
pub confidence_score: f32, // [0.0, 1.0]
pub execution_time_ms: u64,
pub error: Option<String>,
}Each step emits a StepResult with a confidence score. The executor composes scores along the DAG:
- Sequential composition — weakest-link:
min(scores) - Parallel composition — voting: weighted geometric mean
- Retry decay — every retry multiplies the score by
1 - retry_penalty(default0.05) - Skip penalty — a skipped optional step contributes
0.95 × parent_score
This is intentionally simple. Recipe authors who need richer aggregation can register a custom ConfidenceFn on the executor.
Validation
Before execution, the recipe is validated:
- Topological sort via Kahn's algorithm
- Cycle detection (
depends_oncannot form a cycle) - Schema check on every step's
payloadagainst the target protocol's request schema - Capability check — caller must hold capabilities for every protocol referenced
- Gate condition type-check —
BoolExprmust be evaluable with the available bindings
Validation errors surface as RecipeError::Validation { step, reason } before any step executes.
Compilation strategies
A recipe can be authored in three ways:
| Strategy | Latency | When |
|---|---|---|
| Template matching | sub-ms | When the workflow matches a pre-registered recipe template |
| Hybrid seed | ~50ms | User supplies a skeleton; LLM fills only the gaps |
| LLM generation | 100–500ms | Free-form intent → full recipe via Tier 2 routing |
LLM compilation is gated by the recipe-llm-compile capability and is metered through MEAL (tokens dimension) like any other agent call.
Audit + governance
pub struct AuditPoint {
pub step_id: String,
pub event_type: String, // routed to AuditPipeline
pub include_step_io: bool,
}
pub struct GovernanceGate {
pub at_step: String,
pub kind: GateKind, // MAXIM, MACE-quorum, MOAT-treaty
pub on_pass: GateAction,
pub on_fail: GateAction, // Abort | Continue | Escalate(MOOT)
}Every recipe step audited to MAX via the standard pipeline; gates fire additional AuthorizationCheck events with the gate kind.
Default recipes
The repo ships with four reference patterns in DEFAULT_RECIPES.md:
- Grounded Response — retrieve from
MIND→ reason withMARC→ verify viaMAVEN→ audit toMAX - Policy Decision — collect evidence via
MAVEN→ deliberate viaMACE→ consultMAXIM→ enforce - Service Transaction — advertise on
MARKET→ negotiate viaMANA→ settle viaMADE - Agent Deployment — bootstrap identity via
MACS→ register onMARS→ submit manifest toMOON
See Recipes for the full set.
Executor
pub struct Executor {
engine: Arc<MapEngine>,
confidence_fn: Box<dyn ConfidenceFn>,
/// Cached durable journal for replay.
journal: Arc<dyn RecipeJournal>,
}
impl Executor {
pub async fn run(&self, recipe: Recipe, params: Value, ctx: InvokeContext)
-> Result<RecipeRun, RecipeError>;
pub async fn resume(&self, run_id: &str, ctx: InvokeContext)
-> Result<RecipeRun, RecipeError>;
}The journal allows recipes to resume after engine restarts — the same durability guarantee MOON provides for raw workflows, but at the recipe layer.