Multi-Agent Governance
PhronEdge governs agent-to-agent delegation, sub-agent tool calls, and multi-agent pipelines. Every agent in the chain is independently credentialed. No agent inherits permissions from its parent.
The delegation problem
When Agent A delegates to Agent B:
- Who is responsible for Agent B's actions?
- Can Agent B access data Agent A cannot?
- Can Agent B delegate further to Agent C?
- If Agent B is compromised, what is the blast radius?
PhronEdge answers all four with cryptographic enforcement.
Architecture
Lead Agent (T3 clearance)
│
├── delegates to → Sub-Agent 1 (T1 clearance, medical data)
├── delegates to → Sub-Agent 2 (T1 clearance, financial data)
└── delegates to → Sub-Agent 3 (T0 clearance, report only)
Each agent has its own signed credential. The lead agent's credential includes a can_delegate_to field listing which sub-agents it may invoke. The gateway validates this on every delegation.
Example: Insurance claims investigation
from phronedge import PhronEdge
pe = PhronEdge()
# ── Lead Agent: Claims Investigator (T3 clearance) ──
# Can delegate to: medical_reviewer, financial_auditor, report_writer
# Cannot: access medical or financial data directly
@pe.govern("investigate_claim")
def investigate_claim(claim_id):
"""Orchestrate a full claims investigation."""
# Each sub-call is independently governed
medical = review_medical_history(claim_id)
financial = audit_financials(claim_id)
fraud_score = assess_fraud_risk(claim_id, medical, financial)
return generate_investigation_report(claim_id, medical, financial, fraud_score)
# ── Sub-Agent 1: Medical Reviewer (T1, PII_HEALTH clearance) ──
# Can access: patient medical records
# Cannot: access financial data, delegate to other agents
@pe.govern("review_medical_history")
def review_medical_history(claim_id):
"""Pull patient medical history for claims review."""
patient = claims_db.get_patient(claim_id)
return medical_records.get_history(patient.id)
# ── Sub-Agent 2: Financial Auditor (T1, PII_FINANCIAL clearance) ──
# Can access: financial records, transaction history
# Cannot: access medical data, delegate to other agents
@pe.govern("audit_financials")
def audit_financials(claim_id):
"""Review financial records for the claim."""
return finance_db.get_transactions(claim_id)
# ── Sub-Agent 3: Fraud Analyst (T2, CONF clearance) ──
# Can access: aggregated data (not raw PII)
# Cannot: access raw medical or financial records
@pe.govern("assess_fraud_risk")
def assess_fraud_risk(claim_id, medical_summary, financial_summary):
"""Score fraud probability based on aggregated evidence."""
return fraud_model.predict(claim_id, medical_summary, financial_summary)
# ── Sub-Agent 4: Report Writer (T0, PUB clearance) ──
# Can access: summaries only
# Cannot: access any sensitive data or delegate
@pe.govern("generate_investigation_report")
def generate_investigation_report(claim_id, medical, financial, fraud_score):
"""Generate the final investigation report."""
return report_engine.compile({
"claim_id": claim_id,
"medical_summary": medical,
"financial_summary": financial,
"fraud_score": fraud_score,
})
# ── Run the investigation ──
result = investigate_claim("CLM-2025-78912")
What PhronEdge enforces
investigate_claim("CLM-2025-78912")
|
|-- Gateway: Lead agent credential valid? YES
|-- Gateway: Lead agent can delegate to medical_reviewer? YES
|
|-- review_medical_history(claim_id)
| |-- Gateway: Sub-agent 1 credential valid? YES
| |-- Gateway: Sub-agent 1 has PII_HEALTH clearance? YES
| |-- Gateway: Sub-agent 1 in correct jurisdiction? YES
| |-- ALLOWED. Medical data returned.
|
|-- audit_financials(claim_id)
| |-- Gateway: Sub-agent 2 credential valid? YES
| |-- Gateway: Sub-agent 2 has PII_FINANCIAL clearance? YES
| |-- ALLOWED. Financial data returned.
|
|-- assess_fraud_risk(claim_id, medical, financial)
| |-- Gateway: Sub-agent 3 credential valid? YES
| |-- Gateway: Input contains PII? DETECTED
| |-- Gateway: Sub-agent 3 has PII clearance? NO (CONF only)
| |-- BLOCKED. Regulation: GDPR Art. 9 Special Categories
| |-- Investigation halts. No fraud score generated.
The fraud analyst received raw medical data it was not cleared for. PhronEdge blocks the call. The investigation stops at the exact point of violation. Every event is anchored.
Fixing the violation
The solution is not to give the fraud analyst medical clearance. The solution is to sanitize the data before passing it:
@pe.govern("assess_fraud_risk")
def assess_fraud_risk(claim_id, medical_summary, financial_summary):
# medical_summary should be pre-sanitized by the medical reviewer
# to remove PII before reaching this agent
return fraud_model.predict(claim_id, medical_summary, financial_summary)
This is governance by design. The architecture enforces data minimization.
Example: Customer support with escalation
pe = PhronEdge()
# ── Tier 1: Frontline Agent (T0, PUB clearance) ──
@pe.govern("handle_inquiry")
def handle_inquiry(customer_id, question):
"""Handle basic customer inquiries."""
answer = knowledge_base.search(question)
if answer.confidence < 0.7:
return escalate_to_specialist(customer_id, question)
return answer
# ── Tier 2: Specialist Agent (T1, INT clearance) ──
@pe.govern("escalate_to_specialist")
def escalate_to_specialist(customer_id, question):
"""Handle complex inquiries with access to internal systems."""
customer = crm.get_profile(customer_id)
history = tickets.get_history(customer_id)
return specialist_model.respond(question, customer, history)
# ── Tier 3: Account Manager (T2, CONF clearance) ──
@pe.govern("escalate_to_account_manager")
def escalate_to_account_manager(customer_id, question, context):
"""Handle sensitive account issues with full access."""
account = billing.get_full_account(customer_id)
return account_manager_model.resolve(question, account, context)
# Tier 1 can only delegate to Tier 2.
# Tier 2 can only delegate to Tier 3.
# Tier 1 cannot skip to Tier 3.
# Each tier has progressively higher data clearance.
# PhronEdge enforces the escalation chain.
Example: Multi-model pipeline
pe = PhronEdge()
# Agent 1: Uses GPT-4o for analysis
@pe.govern("analyze_document")
def analyze_document(doc_path):
return openai_client.chat(model="gpt-4o", messages=[
{"role": "user", "content": f"Analyze: {read_file(doc_path)}"}
])
# Agent 2: Uses Claude for summarization
@pe.govern("summarize_analysis")
def summarize_analysis(analysis):
return anthropic_client.messages.create(
model="claude-sonnet-4-20250514",
messages=[{"role": "user", "content": f"Summarize: {analysis}"}]
)
# Agent 3: Uses Gemini for translation
@pe.govern("translate_summary")
def translate_summary(summary, target_lang):
return gemini_client.generate(f"Translate to {target_lang}: {summary}")
# Each agent is credentialed for its specific model.
# Agent 1 cannot use Claude. Agent 2 cannot use GPT-4o.
# The credential's permitted_models field enforces this.
# If someone swaps models at runtime, the gateway blocks it.
Credential structure for multi-agent
When you sign a policy in the console, each agent gets:
Agent: claims-investigator
Tier: T3
Permitted tools: [investigate_claim]
Permitted models: [gpt-4o]
Data classifications: [PUB, INT]
Can delegate to: [medical_reviewer, financial_auditor, report_writer]
Agent: medical-reviewer
Tier: T1
Permitted tools: [review_medical_history]
Permitted models: [gpt-4o]
Data classifications: [PUB, INT, CONF, PII, PII_HEALTH]
Can delegate to: [] # Cannot delegate
Agent: financial-auditor
Tier: T1
Permitted tools: [audit_financials]
Permitted models: [gpt-4o]
Data classifications: [PUB, INT, CONF, PII, PII_FINANCIAL]
Can delegate to: []
Agent: report-writer
Tier: T0
Permitted tools: [generate_investigation_report]
Permitted models: [claude-sonnet-4-20250514]
Data classifications: [PUB]
Can delegate to: []
Every field is cryptographically signed. Tamper with any value and the signature verification fails. The agent cannot execute.
Kill switch in multi-agent systems
If you kill the lead agent, all delegated calls stop immediately:
Kill switch activated: claims-investigator
|
|-- investigate_claim: KILLED
|-- review_medical_history: still callable by other lead agents
|-- audit_financials: still callable by other lead agents
If you kill a sub-agent, only calls to that specific agent stop. Other sub-agents and the lead agent continue operating.
If you quarantine a sub-agent, its calls are blocked pending review but the lead agent can still delegate to other sub-agents. The investigation continues with reduced capability.
Tamper detection in chains
If any credential in the chain is tampered:
Gateway detects ECDSA signature mismatch
→ Pulls original credential from vault
→ Restores the authentic credential
→ Resumes operation
→ Anchors tamper event to hash chain
→ Alerts CISO via configured channels
The agent that was tampered never executes with the modified credential. The vault recovery happens in under 5 seconds.
Next steps