Why Agent Management Fails Without policy.md
Why Agent Management Fails Without policy.md
We talked in recent days: every agent should have a place in your org chart, with a clear owner. But that only tells you who is accountable. It does not tell you what the agent will do, what rules it must follow.
Imagine a manager hires a new sales rep. On day one, what does the manager say? “I want you to bring in new customers.” Is that enough? No. The new hire also needs to know:
- What price range can I offer?
- How much discount can I give to different customer types?
- If a customer asks for net-30 payment terms, what do I say?
- Can I close a high-risk deal on my own, or do I need to ask you?
- What do I report to you every week?
These questions need written answers. For an autonomous agent, this file is called policy.md.
policy.md: The Written Operating Rules
Especially for an autonomous (non-human) agent, policy.md is critical. The agent cannot chat, cannot observe a situation and adapt. When it receives a task, it looks to the code — and the code looks to policy.md.
An example policy.md:
# Agent: Support Ticket Triage Agent (support_triager_001)
## Responsibility
- Classify incoming support tickets by priority level
- Distinguish product bugs from user errors
- Escalate critical failures to engineering immediately
## Access (Skills)
- Tool: Support ticket API (read/write)
- Tool: Slack (team notification)
- Limit: Do not process more than 1,000 tickets per week
- Blocked: Write access to customer records, invoice processing
## Error Handling
- Unclear ticket: Ask the team via Slack
- Same issue appears in 3+ tickets: Mark as "recurring issue"
- Missing data: Send auto-reply to customer, ask to complete
## Reporting
- Daily: Post summary to Slack #support-ops (ticket count, classification, avg response time)
- Weekly: Upload trend data to spreadsheet (patterns, new issue types)
With this policy, the agent knows:
- Which tools it can access
- When to ask for human help
- What to report
- What situations are out of scope
An Agent’s Lifecycle: Draft, Active, Retired
An agent does not go live in production on day one.
Draft Newly built, developer tested, but not yet approved by the organization. The policy.md may be incomplete, skills not fully validated. Lives in a Git branch, not main. Production systems do not run this agent yet.
Active
policy.md is complete, tests pass, owner says “I accept this responsibility.” Marked status: active in config. In Git main. Doing real work. If it fails, the owner answers for it.
Inactive
No longer needed. Maybe another agent does the job better, or the job is no longer needed. We do not delete it — it stays in Git history. But marked status: inactive. Perhaps we will need it again.
agents:
support_triager_001:
name: "Support Ticket Triage Agent"
owner: "person_Ali_Support"
status: active
created: 2026-08-20
policy: "policy/support_triager_001.md"
old_report_bot:
name: "Old Report Generator"
owner: "person_Zeynep_Analytics"
status: inactive
created: 2025-06-10
retired: 2026-08-15
policy: "policy/old_report_bot.md"
What does this design give you? Accountability. Every agent has an owner. Every agent’s rules are in Git. If rules change, a human reviews it in a PR. Who did what, why, and who is responsible is traceable.
Agent Skill Types: Each Carries Different Risks
Regardless of which tools an agent uses, each type must be controlled differently.
builtin — Written directly in the agent’s code
- Text processing, simple math, data structure transformation
- Safe: visible in Git, subject to code review
- Fast: no external calls
mcp (Model Context Protocol) — External system via standard interface
- APIs of well-known systems: Slack, GitHub, Jira
- Managed: built-in auth, rate limiting available
- Risk: API versions change, breaks possible
http — Free-form HTTP call
- Call an external REST API
- Risky: requires URL validation, mandatory timeout and rate limit
- Policy must specify which URLs are allowed, which are forbidden
function — External code (Python/Node.js)
- Database query, ML model call, custom logic
- Most risky: runs external code, needs error handling
- Policy must describe what it does, resource limits, timeout
skills:
- type: builtin
name: "ticket_categorize"
- type: mcp
name: "slack_notify"
config:
channel: "#support-ops"
- type: http
name: "fetch_customer_data"
config:
base_url: "https://api.internal.our-company/customers"
timeout: 10
rate_limit: 100_per_hour
- type: function
name: "calculate_priority_score"
config:
runtime: python
path: "functions/priority_scorer.py"
timeout: 5
Each skill must be clearly described in policy.md. “How many times per day can this skill be called?”, “What happens on error?”, “Where do results go?” All must be specified.
Why policy.md and Git Work Together
The policy.md file lives in your config repo, in Git. When it needs to change, someone opens a PR. A human reviews, change is approved or rejected.
This is the only reliable way to say “I tested this agent, no issues.” Because Git history shows exactly who changed what, when, and why — with human approval stamps.
Compare that to: someone writes a custom system prompt for ChatGPT. Nobody knows what it does. If it makes a bad decision? No policy, no accountability, no trail.
But with policy.md in Git, the agent’s rulebook is public. If someone wants to know why this rule exists, they open Git history, see when it was added, see the PR discussion, find the owner.
Tomorrow: How does one agent hand off work to another? A2A delegation, approval flow, result tracking.