Skip to main content

systemprompt_identifiers/
agent.rs

1//! Agent identity newtypes: opaque [`AgentId`] (UUID-backed), validated
2//! [`AgentName`] (non-empty, reserves `"unknown"`), and
3//! [`ExternalAgentId`] for off-platform "super-agents" (Claude Desktop,
4//! Codex CLI, Claude Code) that connect via the bridge binary.
5
6crate::define_id!(AgentId, generate, schema);
7crate::define_id!(ExternalAgentId, non_empty);
8
9use crate::error::IdValidationError;
10
11#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, schemars::JsonSchema)]
12#[cfg_attr(feature = "sqlx", derive(sqlx::Type))]
13#[cfg_attr(feature = "sqlx", sqlx(transparent))]
14#[serde(transparent)]
15pub struct AgentName(String);
16
17impl AgentName {
18    pub fn try_new(name: impl Into<String>) -> Result<Self, IdValidationError> {
19        let name = name.into();
20        if name.is_empty() {
21            return Err(IdValidationError::empty("AgentName"));
22        }
23        if name.eq_ignore_ascii_case("unknown") {
24            return Err(IdValidationError::invalid(
25                "AgentName",
26                "'unknown' is reserved for error detection",
27            ));
28        }
29        Ok(Self(name))
30    }
31
32    #[expect(
33        clippy::expect_used,
34        reason = "infallible constructor reserved for already-validated inputs; untrusted input \
35                  must go through try_new"
36    )]
37    pub fn new(name: impl Into<String>) -> Self {
38        // SAFETY: `new` is the infallible constructor reserved for inputs the caller
39        // has already validated (compile-time literals, values that
40        // round-tripped through `try_new` at a boundary). Untrusted input must
41        // go through `try_new`.
42        Self::try_new(name).expect("AgentName validation failed")
43    }
44
45    pub fn as_str(&self) -> &str {
46        &self.0
47    }
48
49    pub fn system() -> Self {
50        Self("system".to_owned())
51    }
52}
53
54crate::__define_id_validated_conversions!(AgentName);
55crate::__define_id_common!(AgentName);