Skip to main content

made_core/ports/
agent_resolver.rs

1//! [`AgentResolverPort`] — resolve agent identities into concrete
2//! [`AgentPort`] instances.
3//!
4//! The [`Council`](crate::entities::Council) aggregate stores only
5//! [`AgentId`]s to keep the domain pure of runtime objects. Use cases
6//! that need to actually ask agents to propose / critique / revise
7//! go through this port to obtain the live handles.
8//!
9//! Adapters typically back this port with an in-memory registry, a
10//! factory that materializes agents from config, or a cache in front
11//! of a remote agent service. MADE itself never knows.
12
13use std::sync::Arc;
14
15use async_trait::async_trait;
16
17use crate::error::DomainError;
18use crate::ports::agent::AgentPort;
19use crate::value_objects::AgentId;
20
21#[async_trait]
22pub trait AgentResolverPort: Send + Sync {
23    /// Resolve a single agent identity. Returns
24    /// [`DomainError::NotFound`] when the id is unknown to the adapter.
25    async fn resolve(&self, id: &AgentId) -> Result<Arc<dyn AgentPort>, DomainError>;
26
27    /// Resolve a batch of agent identities preserving input order.
28    /// Returns [`DomainError::NotFound`] on the first unresolved id.
29    ///
30    /// Default implementation calls [`Self::resolve`] in order; adapters
31    /// can override to batch lookups.
32    async fn resolve_all(&self, ids: &[AgentId]) -> Result<Vec<Arc<dyn AgentPort>>, DomainError> {
33        let mut out = Vec::with_capacity(ids.len());
34        for id in ids {
35            out.push(self.resolve(id).await?);
36        }
37        Ok(out)
38    }
39}