#[non_exhaustive]pub struct BindingContext {
pub agent_id: String,
pub session_id: Option<Uuid>,
pub channel: Option<String>,
pub account_id: Option<String>,
pub binding_id: Option<String>,
pub mcp_channel_source: Option<String>,
pub event_source: Option<EventSourceMeta>,
pub tenant_id: Option<String>,
pub language: Option<String>,
}Expand description
Phase 82.1 — binding context propagated to tool calls so extensions and MCP servers can route per-(channel, account_id, agent_id) tuple without re-deriving it from each tool call’s payload.
Serialised under _meta.nexo.binding in JSON-RPC tools/call
(extensions ignore unknown fields) and as the meta block of
MCP call_tool_with_meta.
agent_id is mandatory; the rest are Option because some
dispatch paths (delegation receive, heartbeat bootstrap, tests)
have no binding match — None is the correct state, not a
sentinel string.
mcp_channel_source is populated when the inbound that
triggered this turn arrived via a Phase 80.9 MCP channel
server (e.g., "slack", "telegram"). Lets a tool
distinguish “telegram-binding answered via MCP slack server”
from “telegram-binding answered via native Telegram plugin”
while still seeing the same (channel, account_id) binding
tuple. Matches the goal_turns.source = "channel:slack"
audit column shipped with Phase 80.9.
Identifies which inbound binding a tool call originated from.
Stamped on every tool call dispatched to a Phase 11 stdio
extension or a Phase 12 MCP server (under params._meta.nexo.binding).
A microapp reads it to route work to the correct tenant /
channel / account.
binding_id is rendered as <channel>:<account_id|"default">
— a stable identifier that survives agents.yaml reloads
(does NOT depend on the binding vector index).
mcp_channel_source is populated when the inbound that
triggered the call arrived via a Phase 80.9 MCP channel
server ("slack", "telegram", etc.), allowing a tool to
distinguish “telegram-binding answered via MCP slack server”
from “telegram-binding answered via the native Telegram
plugin” while still seeing the same (channel, account_id)
tuple.
§Example
use nexo_tool_meta::BindingContext;
let ctx = BindingContext::agent_only("ana");
assert_eq!(ctx.agent_id, "ana");
assert!(ctx.channel.is_none());Fields (Non-exhaustive)§
This struct is marked as non-exhaustive
Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.agent_id: StringStable agent identifier (agents.yaml.<id>).
session_id: Option<Uuid>Active session UUID. None outside an LLM turn (heartbeat
bootstrap, delegation receive, tests).
channel: Option<String>Channel name as declared in InboundBinding.plugin
("whatsapp", "telegram", "email", "web", …).
None for contexts without a binding match.
account_id: Option<String>Account / instance discriminator from
InboundBinding.instance. None when the binding
declared no instance (single-account default).
binding_id: Option<String>Stable binding identifier rendered as
<channel>:<account_id|"default">. None for
bindingless contexts.
mcp_channel_source: Option<String>Phase 80.9 — MCP channel server name when the inbound
arrived via notifications/nexo/channel. None for
native-channel inbounds. Examples: "slack",
"telegram", "imessage".
event_source: Option<EventSourceMeta>Phase 82.4 — event-subscriber metadata when the agent’s
inbound was synthesised from a NATS event (subject pattern
match). None for human-message turns / native-channel
inbounds.
tenant_id: Option<String>Phase 83.8.12 — SaaS tenant (tenant) key. None for
agents that predate the multi-tenant model
(agents.yaml.<id> without an tenant_id field).
Multi-tenant filtering across admin RPC + microapp tools
keys on this field. Sits ABOVE account_id, which
remains the channel-side discriminator.
language: Option<String>Phase 81.19.b locale follow-up item 6 — resolved BCP-47
locale for this binding (InboundBinding.language over
AgentConfig.language). When present, the SDK’s STT
inbound transform handler trims to ISO-639-1 and passes
it as a hint to whisper for accented audio. None lets
whisper auto-detect.
Implementations§
Source§impl BindingContext
impl BindingContext
Sourcepub fn agent_only(agent_id: impl Into<String>) -> BindingContext
pub fn agent_only(agent_id: impl Into<String>) -> BindingContext
Build the minimum context for a path that has no binding
(delegation receive, heartbeat bootstrap, tests). Every
optional field stays None.
Sourcepub fn with_mcp_channel_source(
self,
source: impl Into<String>,
) -> BindingContext
pub fn with_mcp_channel_source( self, source: impl Into<String>, ) -> BindingContext
Builder helper: layer the MCP channel source on an already-built context. Lets the runtime distinguish a telegram-binding answered via MCP-slack from the same binding answered via the native Telegram plugin.
Sourcepub fn binding_id(&self) -> Option<&str>
pub fn binding_id(&self) -> Option<&str>
Cheap accessor — returns the stable
<channel>:<account_id|"default"> identifier when
available. None for bindingless contexts.
Trait Implementations§
Source§impl Clone for BindingContext
impl Clone for BindingContext
Source§fn clone(&self) -> BindingContext
fn clone(&self) -> BindingContext
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for BindingContext
impl Debug for BindingContext
Source§impl<'de> Deserialize<'de> for BindingContext
impl<'de> Deserialize<'de> for BindingContext
Source§fn deserialize<__D>(
__deserializer: __D,
) -> Result<BindingContext, <__D as Deserializer<'de>>::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(
__deserializer: __D,
) -> Result<BindingContext, <__D as Deserializer<'de>>::Error>where
__D: Deserializer<'de>,
Source§impl PartialEq for BindingContext
impl PartialEq for BindingContext
Source§fn eq(&self, other: &BindingContext) -> bool
fn eq(&self, other: &BindingContext) -> bool
self and other values to be equal, and is used by ==.Source§impl Serialize for BindingContext
impl Serialize for BindingContext
Source§fn serialize<__S>(
&self,
__serializer: __S,
) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>where
__S: Serializer,
fn serialize<__S>(
&self,
__serializer: __S,
) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>where
__S: Serializer,
impl Eq for BindingContext
impl StructuralPartialEq for BindingContext
Auto Trait Implementations§
impl Freeze for BindingContext
impl RefUnwindSafe for BindingContext
impl Send for BindingContext
impl Sync for BindingContext
impl Unpin for BindingContext
impl UnsafeUnpin for BindingContext
impl UnwindSafe for BindingContext
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more