FruxonDocs

Agent Network

Wire triggers, participants, channels, and approval roles around your agents

Agent Network is the tenant-level place where you wire what can start an agent and who an agent can talk to. It is built on two durable resources:

  • Triggers — events that fire one or more agents.
  • Participants — people, groups, or AI agents that can message agents, receive replies, or fill approval roles.

Integrations still own credentials and capability metadata. A Slack, Telegram, Twilio, GitHub, Gmail, or Outlook config tells Fruxon how to authenticate and what the provider can emit. The Agent Network resources are the tenant-level runtime wiring that uses those configs.

Mental model

ResourceWhat it answersWhere it lives
IntegrationWhat can this provider do? Tools, trigger types, and channel types.Integrations
Integration configWhich credentials or workspace should Fruxon use?Integrations
TriggerWhich event should start which agents?Agent Network
ParticipantWho or what can talk to agents, and through which addresses?Agent Network
ConversationWhich external thread has Fruxon observed?Agent Network / Conversations
Access requestWhich unknown sender wants to be added to the participant graph?Agent Network

Triggers and participants are flat tenant resources. They are not nested under a single integration because they can cut across integrations: a schedule trigger has no provider at all, and one participant can have Slack, Telegram, Teams, and phone channels on the same row.

Triggers

A trigger is a configured event source that can fire one or more agents. Fruxon supports three kinds:

Trigger kindExamplesNotes
ScheduleCron-like recurring runs from the System integration.Does not require an integration config.
WebhookAn inbound HTTP call to a delivery URL.For external systems that POST events to Fruxon.
Integration eventslack.message.received, github.push, google_gmail.message.received, outlook.message.received, twilio.message.received.Usually pinned to an integration config.

Any trigger can also be fired manually (the :fire action) to validate wiring — that's an operator action on a trigger, not a separate kind.

Each integration publishes trigger descriptors with a stable event id, display name, whether a config is required, and payload fields. The trigger picker reads the cross-integration catalog so operators only see integrations that actually emit events.

Bind agents

One trigger can fire many agents. Bindings are managed separately from the trigger details so you can add or remove an agent without recreating the event source. Each binding can also carry payload-to-parameter mappings, so the same inbound event can feed different agent inputs.

Use the event payload namespaces consistently:

NamespaceMeaning
{{payload.*}}Raw provider or normalized inbound-event data, such as payload.text, payload.from, or payload.message_attributes.thread_ts.
{{trigger.*}}Trigger execution context, such as fire time and timezone, available at run time.

Filter events

Integration-event triggers can include a content filter. The structural match happens first: integration, config, and event type. The filter runs after that against payload.* and decides whether the matched event actually fires the bound agents.

Filters are condition trees, not code. They support ALL / ANY matching and operators such as EQUALS, IN, CONTAINS, EXISTS, and numeric comparisons. A missing filter, or a filter with zero conditions, fires every structurally matched event.

Good uses:

  • Fire only when a GitHub issue has an urgent label.
  • Drop Slack messages from the bot itself.
  • React only to messages from an allowlisted email sender.

Manual :fire and schedule runs bypass the content filter because the operator or scheduler is already naming the trigger directly. Use trigger preview to test a sample payload before wiring a provider webhook.

Participants

A participant is a tenant-level actor that can address agents or receive outbound messages from agents. People and groups are managed in the Directory; "participant" is the umbrella term for both. Participants can be:

KindUse it for
PersonOne human reachable through one or more provider addresses.
GroupA Slack channel, Telegram group, Teams channel, phone line, or similar shared venue.
AI AgentAnother Fruxon agent represented as an actor in async routing or approval workflows.

Channels are stored inline on the participant. Each channel points to an integration config and a provider-specific address:

FieldMeaning
integrationConfigIdThe credentials envelope or workspace used to send and receive.
addressProvider-specific address: Slack channel/DM id, Telegram chat id, Teams conversation id, phone number, etc.
priorityHigher priority wins when several channels are available.
labelHuman-friendly label shown in the UI.
disabledPauses one channel without disabling the whole participant.

Bind a participant to an agent to let that participant address the agent. Disable the participant to pause all inbound and outbound routing while preserving channels and bindings.

Participant avatars

Participant.avatarFileId is the source of truth for the participant's image. Operators can upload an avatar directly, and supported providers can sync one from a channel. Slack and Telegram support sync today. AI-agent participants without an explicit avatar inherit the backing agent avatar at read time, without writing that fallback onto the participant row.

Identity and linked accounts

A participant carries a profile beyond its channels — display name, email, role, a short description, and optional area of work, bio, and preferences. This is the identity an agent reasons about and the memory it scopes to a person.

Separately from the addresses it's reachable at, a participant can list linked accounts — external profiles that identify the same person on other products (GitHub, GitLab, Jira, Linear, Confluence, Notion, Asana, Bitbucket). These are correlation references only: an account answers "who is this on GitHub?", never "where do I send a reply." Fruxon never matches inbound traffic or routes outbound messages on an account — that's what addresses are for.

SurfaceWhat it's forUsed for routing?
AddressesWhere the participant is reachable (Slack id, phone, email channel, …)Yes — matched on inbound, chosen on outbound
Linked accountsWho the participant is on other productsNo — reference / correlation only

Each linked account records a provider, an identifier, and an optional handle, and is marked Verified or Discovered (auto-found by the profile agent, not yet confirmed).

Agents can resolve identity at run time with the built-in resolve_participant tool: given a {provider, identifier} pair or an email, it returns the matching participant — id, kind, display name, email, role, and all of their addresses and linked accounts. It's the reverse of looking a user up by channel, and it's how an agent correlates "the person who filed this GitHub issue" with "the Slack user I'm talking to." The agent threads the resolved reference into its product tools but always acts with its own integration credentials — never as the person.

Auto-discovered senders (an unknown person in a public channel) are minted as ambient participants for identity and memory continuity, but kept out of the curated roster until you promote them by approving an access request — so the directory stays the people you chose, not everyone who ever messaged.

Reply policy

When a participant is bound to an agent, the binding carries a reply policy that decides whether an inbound message actually gets a reply. It's set per edge — the same participant can be chatty with one agent and quiet with another — from the Reply policy column on the roster.

Reply policyThe agent replies…
Always reply (default)To every message from this participant.
Only when addressedOnly when the message names or @-mentions the agent. Good for busy group channels where the agent shouldn't jump into every thread.
When relevantOnly when a fast relevance pre-gate judges the message is actually meant for the agent.

The relevance pre-gate (Silencer). With When relevant, every inbound message first runs a cheap LLM check before the full agent run. The gate returns respond-or-stay-silent; if it says silent, no run happens and nothing is sent. It's how an agent sits in a noisy channel and only speaks up when it has something to add — instead of replying to every message (Always) or needing to be explicitly named (Only when addressed).

The gate is tuned per agent. Setting a binding to When relevant reveals a Silencer settings control on the roster:

SettingDefaultWhat it does
ModelSame as agentWhich model judges relevance. Use a small, cheap model — this runs on every message.
Max output tokensCaps the gate's tiny JSON verdict.
Context turns6How many recent conversation turns the gate sees, so it can judge in context. 0 disables the tail.
System prompt overrideReplaces the default judgement instructions when your channel needs a custom notion of "relevant."

The gate fails open: any error, timeout, or ambiguous verdict resolves to respond, so a flaky check never silently swallows a real message. And if the agent is over its budget, the gate is bypassed and the message is handled normally — relevance gating never becomes a backdoor budget block.

Watching it. The agent Overview's Relevance card rolls up the gate's decisions: the silence rate, counts of Responded / Silenced / Bypassed (over-budget), the gating cost, and a time-range selector. Check it to confirm the gate is silencing noise, not real intent — if your silence rate looks too high, loosen the instructions or switch the binding back to Only when addressed.

Conversations and messages

Conversations are observed external threads: a Slack channel, Telegram chat, Teams thread, Twilio number, or similar address. They are tenant-level resources observed through one or more integration configs. The config is a lens, not the parent.

That distinction matters when you have multiple configs for the same provider. Filtering by integrationConfigId asks "what did this credential observe?" without duplicating the underlying thread as a separate resource.

Common filters:

FilterUse it for
integrationConfigIdShow traffic through one workspace, bot, app, or phone number.
agentIdShow conversations involving one agent.
participantIdShow conversations reachable through one participant.
triggerIdShow conversations linked to executions fired by one trigger.
onlyDiscoveredShow provider-discovered addresses before any real traffic arrives.

Access requests

Access requests are participants-native onboarding. When an unknown sender, or a known participant not bound to the addressed agent, sends a message through a participant-owned inbound path, Fruxon records a pending access request and drops the message. Approval commits the proposed graph change.

Approval modes:

ModeWhat happens
Create newCreate a Person participant from the observed sender, add the observed channel, and bind it to the agent.
Add to existingAppend the observed channel to an existing participant and ensure the agent binding.
Bind onlyBind the already-matched participant to the agent.

Rejecting records the operator decision. A later message from the same sender can create a fresh pending request; reject means "not now," not a permanent block.

Human approvals

Human-in-the-loop approval roles are modeled as agent slots. The agent revision declares the slot name and required kind; Agent Network binds that slot to a participant. Because the concrete participant is operator-managed, you can change "who approves legal_review" without creating a new agent revision.

An AI-agent participant can fill an AI-agent slot, so async agent-to-agent approval or delegation uses the same participant graph as human routing.

API

Triggers, participants, bindings, conversations, messages, and the network graph are all managed through the Agent Network API. Inbound webhook URLs live outside the tenant prefix (the path id resolves the tenant server-side), in two shapes: one webhook per config and one per channel binding.

Provider-specific setup details (scopes, tokens, webhook URLs) live on each provider's integration page.

Next steps

On this page