Skip to main content

domain/
agent.rs

1use bon::Builder;
2use nutype::nutype;
3use serde::{Deserialize, Serialize};
4
5use crate::policy;
6
7#[nutype(
8    sanitize(trim),
9    validate(not_empty, len_char_max = 80),
10    derive(
11        Debug,
12        Clone,
13        PartialEq,
14        Eq,
15        PartialOrd,
16        Ord,
17        Hash,
18        Serialize,
19        Deserialize
20    )
21)]
22pub struct Name(String);
23
24#[nutype(
25    sanitize(trim),
26    validate(not_empty, len_char_max = 400),
27    derive(
28        Debug,
29        Clone,
30        PartialEq,
31        Eq,
32        PartialOrd,
33        Ord,
34        Hash,
35        Serialize,
36        Deserialize
37    )
38)]
39pub struct Purpose(String);
40
41#[nutype(
42    sanitize(trim),
43    validate(not_empty, len_char_max = 80),
44    derive(
45        Debug,
46        Clone,
47        PartialEq,
48        Eq,
49        PartialOrd,
50        Ord,
51        Hash,
52        Serialize,
53        Deserialize
54    )
55)]
56pub struct ToolName(String);
57
58#[nutype(
59    sanitize(trim),
60    validate(not_empty, len_char_max = 160),
61    derive(
62        Debug,
63        Clone,
64        PartialEq,
65        Eq,
66        PartialOrd,
67        Ord,
68        Hash,
69        Serialize,
70        Deserialize
71    )
72)]
73pub struct ForbiddenAction(String);
74
75#[nutype(
76    sanitize(trim),
77    validate(not_empty, len_char_max = 400),
78    derive(
79        Debug,
80        Clone,
81        PartialEq,
82        Eq,
83        PartialOrd,
84        Ord,
85        Hash,
86        Serialize,
87        Deserialize
88    )
89)]
90pub struct PolicyInstruction(String);
91
92#[nutype(
93    sanitize(trim),
94    validate(not_empty, len_char_max = 120),
95    derive(
96        Debug,
97        Clone,
98        PartialEq,
99        Eq,
100        PartialOrd,
101        Ord,
102        Hash,
103        Serialize,
104        Deserialize
105    )
106)]
107pub struct OutputSchemaName(String);
108
109#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Builder)]
110/// Domain contract for one bounded automation agent.
111///
112/// A spec describes what an agent is meant to help with, which narrow tools may
113/// be exposed to it, which live operational actions are outside its authority,
114/// and which deterministic review gates must remain in the app workflow.
115pub struct Spec {
116    /// Stable workflow-facing agent name.
117    ///
118    /// This is an identifier such as `manager-daily-brief` or `booking-triage`,
119    /// not a human display label. It connects prompt packets, outputs, and audit
120    /// evidence back to the spec that constrained the agent run.
121    pub name: Name,
122    /// Business purpose for the agent's draft or evidence work.
123    ///
124    /// The purpose should state the resort operation being supported, such as
125    /// summarizing labor risk, drafting customer-safe follow-up, or routing
126    /// vaccine-document ambiguity; it does not grant live-action authority.
127    pub purpose: Purpose,
128    /// Tool names the runtime may expose to this agent.
129    ///
130    /// These should be read-only, draft-only, or task-creation surfaces scoped to
131    /// the workflow. They are the positive capability list for context building,
132    /// not permission to bypass review gates or mutate source systems.
133    pub allowed_tools: Vec<ToolName>,
134    /// Live or unsafe actions the agent must not perform directly.
135    ///
136    /// Examples include confirming bookings, promising availability, changing
137    /// labor schedules, waiving deposits, diagnosing pets, or sending customer
138    /// messages without approval.
139    pub forbidden_actions: Vec<ForbiddenAction>,
140    /// Human or deterministic app review gates required for the workflow.
141    ///
142    /// These gates keep manager approval, customer-message approval, medical
143    /// document review, and similar authority outside the model-generated output.
144    pub default_review_gates: Vec<policy::ReviewGate>,
145}