Types
ProtocolModule trait, InvokeContext, ResolvedAgentIdentity, Response, ProtocolError — quoted from the Rust source.
The MAP engine defines a small, deliberately stable set of types in engine/common/. Everything else builds on these.
ProtocolModule trait
use async_trait::async_trait;
use serde_json::Value;
#[async_trait]
pub trait ProtocolModule: Send + Sync {
/// Canonical protocol name. Static string for fast comparison.
fn protocol_name(&self) -> &'static str;
/// Semantic version of this implementation.
fn version(&self) -> &'static str;
/// All operations this module supports.
fn operations(&self) -> Vec<&'static str>;
/// Dispatch a single operation.
async fn invoke(
&self,
operation: &str,
payload: Value,
ctx: &InvokeContext,
) -> Result<Response, ProtocolError>;
}Every protocol crate in protocols/*-lib implements this trait. Tier-2 WASI plugins implement it via wit-bindgen and the Wasmtime 37 component model. Tier-3 external HTTP protocols are wrapped by RemoteProtocolModule in engine/core/src/external.rs.
InvokeContext
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct InvokeContext {
/// UUID v4. Threaded through the entire request flow.
pub correlation_id: String,
/// Organizational tenant scope for the call.
pub tenant_id: String,
/// Caller DID (did:oas:...).
pub agent_did: String,
/// Filled by IdentityMiddleware::enrich before handle_request.
pub resolved_identity: Option<ResolvedAgentIdentity>,
/// W3C Trace Context — traceparent + tracestate.
pub trace_context: Option<TraceContext>,
/// RFC3339 timestamp at the gateway ingress.
pub timestamp: String,
/// Free-form metadata map. Plugins read their config from here.
pub metadata: HashMap<String, Value>,
}Helpers on InvokeContext
impl InvokeContext {
pub fn identity(&self) -> Option<&ResolvedAgentIdentity>;
pub fn caller_entity_kind(&self) -> AgentEntityKind;
pub fn caller_human_root(&self) -> Option<&str>;
pub fn caller_lineage_verified(&self) -> bool;
pub fn plugin_config(&self) -> Option<&Value>;
}Use these instead of poking at the fields directly — identity() returns None if the resolver failed, and caller_lineage_verified() quietly returns false for unresolved callers.
Response
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Response {
pub data: Value,
pub metadata: Option<HashMap<String, Value>>,
}Every protocol returns this. The engine extracts data into HandleRequestOutput::output; metadata flows through the audit pipeline.
ProtocolError
#[derive(thiserror::Error, Debug)]
pub enum ProtocolError {
#[error("unknown operation: {0}")]
UnknownOperation(String),
#[error("invalid payload: {0}")]
InvalidPayload(String),
#[error("capability missing: {0}")]
MissingCapability(String),
#[error("policy denied: {reason}")]
PolicyDenied { reason: String },
#[error("adapter error: {0}")]
AdapterError(String),
#[error("timeout")]
Timeout,
#[error("internal: {0}")]
Internal(String),
}ProtocolError is mapped to CoreError by ProtocolRouter::invoke using simple heuristics on the error message (looking for adapter, timeout, invalid). See Router for the mapping.
ResolvedAgentIdentity
The identity record attached by IdentityMiddleware::enrich. Defined in engine/common/src/identity.rs:
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ResolvedAgentIdentity {
pub did: String,
pub entity_kind: AgentEntityKind,
pub name: Option<String>,
pub human_root_did: Option<String>,
pub lineage_depth: u32,
pub lineage_verified: bool,
pub creator_did: Option<String>,
pub conformance_level: ConformanceLevel,
pub capabilities: Vec<AgentCapability>,
pub service_endpoints: Vec<AgentServiceEndpoint>,
pub revoked: bool,
pub auth_method: String,
pub extended: HashMap<String, Value>,
}AgentEntityKind
pub enum AgentEntityKind {
HumanRoot,
MultiHumanRoot,
EntityNameRecord,
Agent,
AgentInstance,
Tool,
Skill,
Workflow,
Model,
Dataset,
Service,
Unknown(String),
}The first three are root kinds — every other agent's lineage must terminate at a root. Unknown(String) exists for forward-compatibility with new entity kinds in OAS.
ConformanceLevel
pub enum ConformanceLevel {
L0, // minimal: DID exists, no lineage
L1, // standard: lineage verified for non-roots
L2, // enhanced: full extended sections, attestations, reputation
}Most production calls require L1. Tier-2 capabilities (cross-org settlement, governance ratification) may require L2.
Helpers
impl ResolvedAgentIdentity {
pub fn is_human_root(&self) -> bool;
pub fn is_autonomous_org(&self) -> bool;
pub fn has_verified_lineage(&self) -> bool;
pub fn effective_root_did(&self) -> &str;
pub fn has_capability(&self, name: &str) -> bool;
pub fn local_admin() -> Self; // dev only
pub fn unresolved(did: &str) -> Self; // fallback when resolution fails
}ResolvedAgentIdentity::local_admin() exists for dev-mode only. It returns an identity with full wildcard capabilities and lineage_verified = true. The production gateway never returns it; production tenants are configured with explicit capability sets.
AgentCapability
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct AgentCapability {
/// Hierarchical capability name. e.g. "map.macs.auth_negotiation"
/// or "map.mind.*" for protocol-wildcard.
pub name: String,
/// Optional time-bound expiry.
pub expires_at: Option<chrono::DateTime<chrono::Utc>>,
/// Spending / rate ceiling specific to this capability.
pub limits: Option<CapabilityLimits>,
/// Caveats — additional constraints (jurisdiction, time-of-day, etc.).
pub caveats: Vec<String>,
}The SecurityGateway matches name hierarchically: exact match first, then protocol-wildcard (map.{protocol}.*), then global-wildcard (map.*.*).
AgentServiceEndpoint
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct AgentServiceEndpoint {
pub kind: String, // "did-auth" | "mcp" | "a2a" | ...
pub url: String,
pub protocols: Vec<String>,
}Used for callbacks during multi-stage auth flows and for cross-organization discovery via MARS::discovery.
See also
MapEngine::handle_request— entry point- Router — how
ProtocolRouterdispatches and caches modules - Middleware — how
ResolvedAgentIdentitygets populated