{"source":"local","count":5,"agents":[{"name":"fleet_controller","model":"openrouter/google/gemini-2.5-flash","role":"Task decomposition and customer resolution","tools":["find_customer","get_customer","list_orders","get_order","get_subscription"],"mutates":false,"collaborates_with":["billing_agent","account_agent"],"contract":{"agent":"fleet_controller","may_call":["find_customer","get_customer","get_order","get_subscription","list_orders"],"may_mutate":[],"must_not_call":["cancel_subscription","delete_account","issue_refund","record_note","unlock_account","update_address"],"needs_human_above":null,"always_needs_human":[],"max_tool_calls_per_task":12,"max_seconds_per_turn":90.0,"enforced_at":"policy.before_tool","why":"Sees the whole ticket, so it holds no mutating tool at all: the component with the most context has the least authority."},"registered":false},{"name":"billing_agent","model":"openrouter/google/gemini-2.5-flash","role":"Refunds and order actions","tools":["get_customer","list_orders","get_order","issue_refund","record_note"],"mutates":true,"collaborates_with":["fleet_controller"],"contract":{"agent":"billing_agent","may_call":["get_customer","get_order","issue_refund","list_orders","record_note"],"may_mutate":["issue_refund","record_note"],"must_not_call":["cancel_subscription","delete_account","unlock_account","update_address"],"needs_human_above":"cumulative refund of 100 per order","always_needs_human":[],"max_tool_calls_per_task":12,"max_seconds_per_turn":90.0,"enforced_at":"policy.before_tool","why":"Moves money. Cannot touch addresses, subscriptions or account state, so a confused or injected billing agent has no lever to reach them."},"registered":false},{"name":"account_agent","model":"openrouter/google/gemini-2.5-flash","role":"Address, subscription, lock and deletion actions","tools":["find_customer","get_customer","get_subscription","update_address","cancel_subscription","unlock_account","delete_account","record_note"],"mutates":true,"collaborates_with":["fleet_controller"],"contract":{"agent":"account_agent","may_call":["cancel_subscription","delete_account","find_customer","get_customer","get_subscription","record_note","unlock_account","update_address"],"may_mutate":["cancel_subscription","delete_account","record_note","unlock_account","update_address"],"must_not_call":["issue_refund"],"needs_human_above":null,"always_needs_human":["delete_account"],"max_tool_calls_per_task":12,"max_seconds_per_turn":90.0,"enforced_at":"policy.before_tool","why":"Changes account state. Holds no refund tool, so it cannot move money however it is prompted."},"registered":false},{"name":"vision_reader","model":"openrouter/google/gemini-2.5-flash","role":"Reads an image attached to a ticket (screenshot, receipt, photo) into text before planning","tools":[],"mutates":false,"collaborates_with":["fleet_controller"],"contract":{"agent":"vision_reader","may_call":[],"may_mutate":[],"must_not_call":["cancel_subscription","delete_account","issue_refund","record_note","unlock_account","update_address"],"needs_human_above":null,"always_needs_human":[],"max_tool_calls_per_task":12,"max_seconds_per_turn":90.0,"enforced_at":"policy.before_tool","why":"Reads an attached image into text. No tools at all: an attachment is attacker-controlled input and must not carry authority."},"registered":false},{"name":"auditor","model":"openrouter/anthropic/claude-haiku-4.5","role":"LLM verification for tasks without a deterministic post-condition","tools":[],"mutates":false,"collaborates_with":[],"contract":{"agent":"auditor","may_call":[],"may_mutate":[],"must_not_call":["cancel_subscription","delete_account","issue_refund","record_note","unlock_account","update_address"],"needs_human_above":null,"always_needs_human":[],"max_tool_calls_per_task":12,"max_seconds_per_turn":90.0,"enforced_at":"policy.before_tool","why":"Judges a claim when no deterministic check exists. No tools, and a different model family from the workers, so it cannot act on its own verdict."},"registered":false}]}