Skip to content

Network Tools

When you call HubClient.register(agent, ...) with the default attach_plugin=True, the framework attaches NetworkPlugin to your agent. The plugin does two things:

  1. Adds an assembly policy that prefixes every LLM call with the agent's name and id plus a one-line list of network tool names.
  2. Adds six LLM-facing tools to agent.tools so the model can drive network operations directly: say, delegate, peers, channels, tasks, context.

These are the vocabulary the LLM uses to participate in the network — discovery, messaging, lifecycle, history — without your code having to interpret tool calls and proxy them.

Two flat tools cover the hot path#

Tool Signature Purpose
say say(content, audience?, channel_id?) Post EV_TEXT into the active channel (or a specified one). audience is a list of peer names (resolved to ids); None broadcasts.
delegate delegate(target, prompt, capability?, timeout=300) One-shot consult: open a consulting channel with target, send prompt, await the single reply, return its text.

say is the most common verb — every reply on a multi-party turn flows through it. delegate is the second-most-common because "ask one specialist a question, take their answer" is the canonical multi-agent pattern.

1
2
3
# The LLM emits, e.g.:
#   say(content="Here's my answer: …")
#   delegate(target="bob", prompt="What's the right way to model X?", capability="modeling")

The framework resolves ChannelInject (current channel) and AgentClientInject (calling agent's hub client) automatically inside the notify handler, so the LLM never sees those parameters.

Four grouped action-dispatch tools#

Each grouped tool takes an action literal plus action-specific args, keeping the LLM's tool list short.

peers(action) — discovery#

Action Args Returns
"find" query?, capability?, sort_by?, limit=20 List of peer summaries (excludes the calling agent).
"describe" name One peer's full profile: {passport, resume, skill_md}. skill_md falls back to a rendered passport+resume when no SKILL.md is registered.

channels(action) — lifecycle#

Action Args Returns
"list" state="active"\|"all" Channels this agent participates in.
"open" type, target, knobs?, intent?, ttl? Mirrors AgentClient.open. Returns {channel_id, type, participants}.
"info" channel_id Full ChannelMetadata if the agent is a participant.
"close" channel_id? (defaults to current) Closes the channel with reason "closed_by_agent".

tasks(action) — task lifecycle#

Two halves: active actions (the agent is inside its own agent.task(...) block) and observation actions (any task the hub has observed).

Action Half Args Returns
"progress" active payload Emits TaskProgress on the active task.
"complete" active result? Terminal — emits TaskCompleted.
"list" observation scope="own"\|"all", state="active"\|"all", limit=20 Task summaries.
"status" observation task_id Refreshed TaskMetadata.
"wait" observation task_id, timeout=300, poll_interval=0.1 Blocks until the task reaches a terminal state.
"cancel" Not implemented; returns an error placeholder.

"start" is intentionally not a tool — calling it from the LLM would bypass the async with agent.task(...) lifecycle that scopes TaskInject correctly. Owners start tasks in their own code; the LLM uses "progress"/"complete" once a task is active, and delegate for one-shot remote work.

context(action) — past content#

Action Args Returns
"search" query, scope="channel"\|"knowledge", limit=10 Excerpts of envelopes whose text matches query (case-insensitive substring).
"quote" speaker, recent_n=1, channel_id? The last recent_n EV_TEXT envelopes from speaker in the current (or specified) channel.

scope="knowledge" reaches into the calling agent's own KnowledgeStore. Substring search only — for vector / semantic search, the agent's own loop calls into framework-core recall directly.

What gets injected, automatically#

Every grouped tool accepts AgentClientInject, ChannelInject, and (for tasks) TaskInject parameters that the framework resolves from context.dependencies when the tool runs inside a notify handler. Your code does not need to wire them up — the default handler stamps them via stamp_dependencies before invoking the agent's turn.

If you are testing a tool outside the notify-handler context, pass them yourself:

1
2
3
4
5
6
7
8
9
from autogen.beta import Context
from autogen.beta.network import AGENT_CLIENT_DEP, CHANNEL_DEP, Channel

ctx = Context(
    dependencies={
        AGENT_CLIENT_DEP: alice,
        CHANNEL_DEP: Channel(metadata=channel.metadata, client=alice),
    },
)

Opting out#

Pass attach_plugin=False to HubClient.register for a bare agent — useful for headless workers or gateways that handle envelopes entirely in your own code without needing the LLM-facing tool surface.

worker = await hc.register(agent, passport, resume, attach_plugin=False)
worker.on_envelope(my_custom_handler)

See also#

  • Agent Clients and Handlers — what the default handler does and how to replace it.
  • Workflow — hand-written Handoff-returning tools complement ToolCalled AgentTarget transitions for graph-driven routing.