ag2-network-governance
Skill12 starsChanged 10 days agoApache-2.0View on GitHub
Govern an AG2 multi-agent network hub-side: identity (`Passport`, `Resume`, `ObservedStat`), per-agent `Rule` (`AccessBlock`, `LimitsBlock` with nested `RateBlock` / `InboxBlock`), the swappable `HubArbiter` / `RuleBasedArbiter` / `BaseHubArbiter` (`Allow` / `Deny`) gate, `AuthRegistry` / `AuthAdapter` / `ApiKeyAuth` / `NoAuth` registration auth, channel `Expectation`s with `ExpectationEvaluator` / `Violation` and `audit` / `notify_channel` / `auto_close` handlers, the append-only `hub.audit_log` with `AUDIT_KIND_*` constants, live `HubListener` / `BaseHubListener` fan-out, `register_sweeper`, and capability track records via `TaskMirror` + `Task(owner_id=..., spec=TaskSpec(capability=...))` or `agent.ask(..., capability=...)` (replaces deprecated `agent.task`). Use for access policy, inbox caps, SLAs/timeouts, compliance trails, metrics/alerting, peer ranking by track record. Load after `ag2-network-quickstart`; for handlers, views, LLM network tools and envelopes see `ag2-network-tools-and-views`.
In this repository27 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- ag2-a2aSkill
- ag2-acpSkill
- ag2-add-custom-toolSkill
- ag2-ag-uiSkill
- ag2-eval-comparisonSkill
- ag2-evaluationSkill
- ag2-hitlSkill
- ag2-knowledge-and-memorySkill
- ag2-liveSkill
- ag2-mcpSkill
- ag2-middlewareSkill
- ag2-multimodal-inputSkill
- ag2-network-discussionSkill
- ag2-network-quickstartSkill
- ag2-network-tools-and-viewsSkill
- ag2-network-workflowSkill
- ag2-observers-and-alertsSkill
- ag2-overviewSkill
- ag2-quickstartSkill
- ag2-shell-toolSkill
- ag2-structured-outputSkill
- ag2-subagent-delegationSkill
- ag2-telemetrySkill
- ag2-testingSkill
- ag2-use-builtin-toolsSkill
The file
Files
AG2 Network — Governance
Everything hub-side: identity, rules, the arbiter, auth, expectations, audit, listeners, and capability track records. Every send passes through the hub, so every policy is checked and every observation is read there.
Prerequisite:
ag2-network-quickstart(Hub.open,HubClient.register, channel lifecycle).
When to use
- Restrict who talks to whom, cap inboxes / concurrent channels / delegation depth (
Rule) - Custom access logic — JWT scopes, tenant quotas, federation (
HubArbiter) - Authenticate agents at registration (
AuthRegistry,AuthAdapter) - Channel SLAs and auto-close timing (
Expectation, evaluators, handlers) - Compliance queries (
hub.audit_log), live metrics/alerts (HubListener), periodic jobs (register_sweeper) - Track which agent demonstrably does a capability well (
Resume.observed)
Rules
from ag2.network import AccessBlock, InboxBlock, LimitsBlock, Rule
rule = Rule(
access=AccessBlock(outbound_to=["bob", "research-*"], inbound_from=["*"]), # globs over Passport.name
limits=LimitsBlock(
max_concurrent_channels=5, delegation_depth=2, channel_ttl_default="4h",
inbox=InboxBlock(max_pending=100), # high_water=None -> 80% early warning
),
)
alice = await hc.register(agent, Passport(name="alice", owner="acme"), Resume(), rule=rule)
await hub.set_rule(alice.agent_id, rule) # later change; audited as AUDIT_KIND_RULE_SETViolations raise from open(...) / send(...): AccessDeniedError (access, depth, concurrency) or InboxFull. Denied sends are not audited — they reach HubListener.on_envelope_rejected.
Stored but not enforced by the default RuleBasedArbiter: access.channel_types and limits.rate. Enforce them in a custom arbiter. Field reference: references/rules-arbiter-auth.md.
Arbiter and auth
from ag2.network import BaseHubArbiter, Deny, RuleBasedArbiter
class ScopedArbiter(BaseHubArbiter): # allows every gate you don't override -> re-delegate the others
def __init__(self, inner): # (authorize_register/_channel_open/_inbox/_dispatch) to keep rule checks
self._inner = inner
async def authorize_send(self, envelope, sender, sender_rule, recipients):
if sender.name in BLOCKED:
return Deny("missing net.send scope") # -> AccessDeniedError to the caller
return await self._inner.authorize_send(envelope, sender, sender_rule, recipients)
hub.register_arbiter(ScopedArbiter(RuleBasedArbiter()))Auth: Hub.open(store, auth=AuthRegistry([NoAuth(), ApiKeyAuth({"carol": "k1"}), MyAdapter()])); the passport selects one with Passport(auth=AuthBlock(scheme="api_key", claim={"token": "k1"})); adapters raise AuthError. The hub stores passports without claims, so validate against your own secrets. Details, a full HMAC adapter and wire-security notes: references/rules-arbiter-auth.md.
Expectations
Adapter manifests declare SLAs evaluated by the sweeper (expectation_sweep_interval, default 10s): consulting auto-closes on acks_within(30s) / reply_within(600s); conversation audits max_silence(3600s). Built-in handlers: audit, notify_channel (posts EV_EXPECTATION_VIOLATED), auto_close. The turn_within / warn / hide names on discussion/workflow manifests have no built-in implementation, and knobs={"expectations": ...} is ignored. Customise by registering an adapter with your own manifest.expectations plus hub.register_expectation_evaluator(...). See references/expectations-audit-listeners.md.
Audit and listeners
from ag2.network import AUDIT_KIND_TASK_TERMINATED, BaseHubListener
records = await hub.audit_log.read_all() # dicts: kind, at, + kind-specific ids
ended = [r for r in records if r["kind"] == AUDIT_KIND_TASK_TERMINATED]
class Alerts(BaseHubListener): # override only what you need; all async
async def on_turn_failed(self, channel_id, agent_id, envelope_id, exc): ...
async def on_inbox_pressure(self, agent_id, pending, cap): ...
hub.register_listener(Alerts())Audit kinds: AGENT_REGISTERED / AGENT_UNREGISTERED / RESUME_SET / SKILL_SET / RULE_SET / CHANNEL_CREATED / CHANNEL_CLOSED / CHANNEL_EXPIRED / EXPECTATION_VIOLATED / TASK_TERMINATED / TURN_FAILED (all AUDIT_KIND_*). Records carry ids (agent_id, channel_id, task_id), not tenant names. Field tables, audit_log.subscribe, and register_sweeper / await unregister_sweeper are in the reference.
Capability track records
Capability-tagged task terminals update Resume.observed[cap] (ObservedStat: n, completed, failed, expired, p50_latency_ms) and write AUDIT_KIND_TASK_TERMINATED. Agent.task(...) is deprecated (removed in 1.4.0). Use Task from ag2.task:
from ag2 import Context
from ag2.task import Task, TaskSpec
@worker_agent.tool
async def research(topic: str, ctx: Context) -> str:
"""Research a topic."""
async with Task(
owner_id=worker_agent.name,
spec=TaskSpec(title=f"research: {topic}", capability="research"),
context=ctx, # required: the default handler's TaskMirror listens on this stream
) as task:
await task.progress({"step": "gather"})
result = f"notes on {topic}"
return result
stat = (await hub.get_resume(worker.agent_id)).observed.get("research")For a whole model run, call agent.ask(..., capability="x", ttl_seconds=60) on a stream with a TaskMirror attached, either in a custom handler or a script. The default handler does not pass capability. delegate(capability=...) only records a channel knob. More: references/task-observation.md.
Reading hub state
await hub.get_agent(id_or_name) (Passport), get_resume, get_rule, get_skill, list_agents(kind="agent"|"human"|"remote_agent"), get_channel, list_channels, read_wal, get_task, list_tasks, plus hub.arbiter, hub.auth_schemes, hub.health().
Reference
- references/rules-arbiter-auth.md:
Rulefields and their enforcement, the arbiter protocol, auth adapters, 1.3.0 wire security - references/expectations-audit-listeners.md: evaluators, handlers, custom expectations, audit record fields, listener methods, sweepers
- references/task-observation.md:
Task/ask(capability=)/TaskMirror, migration fromagent.task - Upstream:
website/docs/user-guide/network/expectations_and_audit.mdx,task_observation.mdx,hub_and_identity.mdx;website/docs/user-guide/tasks.mdx
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

