pub struct AgentId { /* private fields */ }Expand description
A validated agent identifier in TypeID format.
The agent ID uniquely identifies an agent and encodes:
- Semantic classification (the prefix)
- Unique identity (the
UUIDv7suffix) - Creation timestamp (encoded in
UUIDv7)
§Format
<prefix>_<suffix> where:
- prefix: 1-63 lowercase letters and underscores
- suffix: 26 character base32-encoded
UUIDv7
§Examples
use agent_uri::AgentId;
let id = AgentId::parse("llm_01h455vb4pex5vsknk084sn02q").unwrap();
assert_eq!(id.prefix().as_str(), "llm");
assert_eq!(id.suffix(), "01h455vb4pex5vsknk084sn02q");
// Create a new agent ID
let id = AgentId::new("llm_chat");
assert_eq!(id.suffix().len(), 26);§Constructing one
AgentId::parse reads an existing ID. The other two mint a fresh one and
differ only in what they do with a prefix the grammar rejects:
AgentId::new rewrites it, AgentId::try_new reports it. Prefer
try_new for any prefix that did not come from your own source.
Implementations§
Source§impl AgentId
impl AgentId
Sourcepub fn new(prefix: &str) -> Self
pub fn new(prefix: &str) -> Self
Creates a new agent ID with the given prefix and a fresh UUIDv7,
sanitizing the prefix if the grammar does not already accept it.
This is the split mti draws, and this crate mints TypeIDs with
mti: create_type_id sanitizes and try_create_type_id refuses.
Sanitizing is described on AgentId::try_new’s counterpart below;
in short, anything outside [a-z_] is dropped, uppercase is folded,
and a prefix left with nothing becomes agent.
§Choosing between this and AgentId::try_new
Sanitizing means you get an agent ID with a prefix, not necessarily
the one you named. That is what you want when the prefix is a label you
wrote: minting an ID should not be fallible over a string literal. It is
not what you want when the prefix arrived from somewhere — a peer, a
config file, a URI — because a rewritten prefix is a different agent
class than the one that was asked for, and silence about that is how a
caller ends up registering under a name it never chose. Untrusted input
belongs in AgentId::try_new or AgentId::parse, which refuse.
§Examples
use agent_uri::AgentId;
// A prefix the grammar already accepts is kept verbatim.
let id = AgentId::new("llm_chat");
assert_eq!(id.prefix().as_str(), "llm_chat");
// Anything else is rewritten rather than refused.
assert_eq!(AgentId::new("LLM Chat!").prefix().as_str(), "llmchat");
assert_eq!(AgentId::new("__llm__chat__").prefix().as_str(), "llm_chat");
assert_eq!(AgentId::new("123").prefix().as_str(), "agent");
// Every one of them is a parsable agent ID.
assert!(AgentId::parse(&AgentId::new("123").to_string()).is_ok());Sourcepub fn try_new(prefix: &str) -> Result<Self, AgentIdError>
pub fn try_new(prefix: &str) -> Result<Self, AgentIdError>
Creates a new agent ID with the given prefix and a fresh UUIDv7,
refusing a prefix the grammar does not accept.
Use this whenever the prefix came from outside your own source: it
reports what AgentId::new would have quietly rewritten.
§Errors
Returns AgentIdError if the prefix is invalid.
§Examples
use agent_uri::AgentId;
assert!(AgentId::try_new("llm_chat").is_ok());
assert!(AgentId::try_new("LLM Chat!").is_err());Sourcepub fn parse(input: &str) -> Result<Self, AgentIdError>
pub fn parse(input: &str) -> Result<Self, AgentIdError>
Parses an agent ID from a string.
§Errors
Returns AgentIdError if:
- The input is empty
- The input exceeds 90 characters
- The prefix is invalid
- The suffix is invalid (not valid base32 or wrong length)
- The separator is missing
Sourcepub const fn prefix(&self) -> &AgentPrefix
pub const fn prefix(&self) -> &AgentPrefix
Returns the prefix (semantic classification).
Sourcepub const fn inner(&self) -> &MagicTypeId
pub const fn inner(&self) -> &MagicTypeId
Returns the underlying MagicTypeId.
Trait Implementations§
Source§impl AsRef<MagicTypeId> for AgentId
impl AsRef<MagicTypeId> for AgentId
Source§fn as_ref(&self) -> &MagicTypeId
fn as_ref(&self) -> &MagicTypeId
Source§impl<'de> Deserialize<'de> for AgentId
Available on crate feature serde only.
impl<'de> Deserialize<'de> for AgentId
serde only.Source§fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
impl Eq for AgentId
Source§impl Ord for AgentId
Orders by the rendered prefix_suffix, which is what
Display writes.
impl Ord for AgentId
Orders by the rendered prefix_suffix, which is what
Display writes.
The comparison is the one this always made; what is gone is the pair of
Strings it used to build to make it. MagicTypeId keeps its own rendering
and hands out a borrow of it, so nothing has to be rendered again here.
MagicTypeId’s own Ord is not that comparison — it sorts by suffix first,
which would order agents by creation time rather than by class.