policy.md and Agent Status: Boundaries, States, and Skills

policy.md and Agent Status: Boundaries, States, and Skills

Yesterday we talked about this: every agent needs a place in your organizational chart, with a clear owner (responsible_id). But naming an agent is not enough. You also need to define what it can do, what it cannot do, which tools it can use, and what limits it must stay within.

Because when an agent receives a task, who does it ask? The same way a human employee does. If a salesperson is new and doesn’t know whether they can offer a customer a guarantee, what are the rules? Where are those rules written?

They should be in “operating policy” files.

policy.md: An Agent’s Operating Rules

An agent needs the following information to operate safely:

  1. What is it responsible for? Which jobs does it do, which does it avoid?
  2. What tools can it access? Database, API, file system, network, external services. Which ones?
  3. What happens if there is an error or risk? Can it ask for approval? Can it delay human intervention?
  4. Who does it report its results to? Directly to its owner, or to a central log?

These rules live in policy.md.

# Agent: Data Cleaner Agent (data_cleaner_001)

## Responsibility
- Cleans incoming CSV files: removes missing rows, duplicates, malformed records
- Rules: RFC 4180 CSV standard, UTF-8 encoding, reject files over 10 MB

## Access
- Tool: S3 bucket "raw_data" (read), "cleaned_data" (write)
- Tool: Slack API (report success/failure)
- Limit: Do not reprocess the same file more than 3 times
- Blocked: Access to human records, external API calls

## Error Policy
- Processing fails: Log to Slack #data-ops
- More than 5 errors: Request human intervention
- Sensitive data detected (SSN, IP): Stop immediately, alert responsible_id

## Reporting
- Daily summary: Slack #data-ops, 08:00 UTC
- Detailed logs: S3 "logs" bucket as .json

See? These rules make it crystal clear what the agent does. And they are versioned in Git. If something changes, a human reviews it in a PR.

Agent States: Draft, Active, Inactive

An agent is not always active. It has a lifecycle.

Draft

Active

Inactive

agents:
  data_cleaner_001:
    name: "Data Cleaner Agent"
    owner: "person_Alice_DataOps"
    status: active        # Currently running
    created: 2026-08-15
    policy: "policy/data_cleaner_001.md"
    
  report_generator_v1:
    name: "Report Generator (Old)"
    owner: "person_Bob_Analytics"
    status: inactive      # Previous version, replaced by v2
    created: 2025-06-01
    retired: 2026-08-01
    policy: "policy/report_generator_v1.md"

Skill Types: An Agent’s Toolkit

What an agent can do is defined by its “skills” — the tools available to it. There are four types:

builtin: Defined in the agent’s code

mcp (Model Context Protocol): Connection to an external system

http: Free-form HTTP call

function: External Python/Node.js function

agents:
  data_cleaner_001:
    skills:
      - type: builtin
        name: "csv_validate"          # RFC 4180 validation
        
      - type: mcp
        name: "slack_notify"          # Send Slack message
        
      - type: http
        name: "call_external_clean"   # Third-party API
        config:
          url: "https://api.cleaning-service.com/clean"
          timeout_sec: 30
          
      - type: function
        name: "db_update"             # Write to database
        config:
          runtime: python
          path: "functions/db_update.py"

What is this design the opposite of? Control and visibility. When an agent is designed, its policy is written, its skills are coded, all of it goes into Git. A human reads it, a PR review runs, approval is given. Then it goes active.

Shadow AI is the opposite. Everyone opens their own ChatGPT, nobody knows what anybody is doing. But in an organization with rules, an agent and its policy are in Git, visible to the world.

Tomorrow we will talk about: how does one agent hand off work to another?