Skip to content
1Claw Academy
Curriculum/Agents & Access Control3 minIntermediate · Lesson 2 of 15

Policies and scoped access

Grant an agent read access to one secret path, then use deny rules and priority to carve exceptions out of a broad grant.

A fresh agent has zero access. Its JWT carries an empty scope list until a human writes a policy. Policies tie a principal to path patterns and permissions, so you decide exactly what an agent can touch.

  • * matches one path segment
  • ** matches zero or more segments (any depth)
  • read: GET a value and list metadata
  • write: PUT and DELETE at matching paths
Watch out

When you create, update, or delete an agent's policy, all of that agent's active JWTs are revoked immediately. The agent must re-exchange its API key to pick up the new scope.

  1. 1

    Export your keys and IDs. Use the values saved from Lesson 1.

    bash
    export ONECLAW_API_KEY="1ck_your_key_here"
    export VAULT_ID="your-vault-uuid-here"
    export AGENT_ID="your-agent-uuid-here"
  2. 2

    Create a policy that lets the agent read only api-keys/openai. The pattern is a single path, so the agent cannot reach anything else in the vault.

    bash
    curl -s -X POST https://api.1claw.co/v1/vaults/$VAULT_ID/policies \
      -H "Authorization: Bearer $ONECLAW_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"principal_type":"agent","principal_id":"'$AGENT_ID'","permissions":["read"],"secret_path_pattern":"api-keys/openai"}'
  3. 3

    Re-exchange the agent key for a fresh JWT. The old token was revoked by the policy change.

    bash
    TOKEN=$(curl -s -X POST https://api.1claw.co/v1/auth/agent-token \
      -H "Content-Type: application/json" \
      -d '{"agent_id":"'$ONECLAW_AGENT_ID'","api_key":"'$ONECLAW_AGENT_KEY'"}' | jq -r .access_token)
  4. 4

    Read the allowed path (works), then try a different path. Both 403 (forbidden) and 404 (not found) confirm the agent cannot access that path.

    bash
    curl -s https://api.1claw.co/v1/vaults/$VAULT_ID/secrets/api-keys/openai \
      -H "Authorization: Bearer $TOKEN"
    curl -s https://api.1claw.co/v1/vaults/$VAULT_ID/secrets/api-keys/stripe \
      -H "Authorization: Bearer $TOKEN"
Tip

Policies also support runtime conditions: an IP allowlist (specific IPs or CIDR ranges) and a time window (allowed hours and days). Add these when an agent runs from known infrastructure.

Your agent can now read one secret path and nothing else, and any policy change takes effect on the very next request.

Policy Engine v2 (v0.47) added three fields that turn policies from a flat allow-list into a real evaluation model: effect, priority, and attribute_conditions.

  • effect: "allow" or "deny". A deny rule lets you punch a hole in a broad allow.
  • priority: an integer; higher wins when two policies both match the same path.
  • attribute_conditions: JSONB for fine-grained matching beyond path, IP, and time.
  1. 1

    Grant the agent broad read access across the vault.

    bash
    curl -s -X POST https://api.1claw.co/v1/vaults/$VAULT_ID/policies \
      -H "Authorization: Bearer $ONECLAW_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{
        "principal_type": "agent", "principal_id": "'$AGENT_ID'",
        "path_pattern": "app/**", "permissions": ["read"],
        "effect": "allow", "priority": 10
      }'
  2. 2

    Now carve out the one prefix it must never read, with a higher priority so it wins the overlap.

    bash
    curl -s -X POST https://api.1claw.co/v1/vaults/$VAULT_ID/policies \
      -H "Authorization: Bearer $ONECLAW_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{
        "principal_type": "agent", "principal_id": "'$AGENT_ID'",
        "path_pattern": "app/billing/**", "permissions": ["read"],
        "effect": "deny", "priority": 100
      }'
  3. 3

    Verify. The first read succeeds, the second is denied by the higher-priority deny rule.

    bash
    1claw secret get app/search/api-key   # allowed
    1claw secret get app/billing/stripe   # denied
Watch out

Priority decides overlaps, not effect. A deny rule does not automatically beat an allow: give it the higher priority, or the broad allow may win.

Decide

An agent needs to read everything under app/ except the billing prefix. You write an allow on app/** with priority 10, and a deny on app/billing/** with priority 5. In testing the agent reads app/billing/stripe successfully.

What is wrong?

Check your understanding

4 questions
1

What access does an agent have before any policy is written?

2

In a policy pattern, what does ** match?

3

What happens to active JWTs when an agent's policy changes?

4

An allow policy on app/** has priority 10 and a deny policy on app/billing/** has priority 5. What happens on a read of app/billing/stripe?