ai
The Agent Rail Card: A One-Page AI Agent Permissions Template
An AI agent permissions template should fix ten things for each job: the job, its trigger, data scope, tool scope, output contract, gate, limits, ledger, evaluation, and owner and kill switch. We call this one-page document a rail card. One card covers one job for one agent on a customer data platform (CDP), and systems enforce each field rather than people remembering it.
By Art Kukharenko · Published · Updated
All AI agent railsWho this is for: security engineers, marketing-operations leads and DPOs who must put something on paper before an agent gets access. You will get the ten fields, a filled example, a map from each field to the system that enforces it, and a workshop plan. This page is part of the AI agent rails method.
Why do AI agents need a written permissions template?
AI agents need a written permissions template because identity systems can say what an agent can reach, but not what it is for. A shared service account plus a system prompt is a common starting point. That setup gives one credential to every job and leaves the limits in text the model may ignore. Afterwards, nobody can say which job did what. OWASP lists ASI03 Identity & Privilege Abuse among its top risks for agentic applications 113.
No shared standard for this exists yet, and identity for agents is still being worked out. The US National Institute of Standards and Technology published a draft concept paper on 5 February 2026, with comments closing on 2 April 2026. It proposes a project on applying existing identity standards to agents, and it asks about identification, authorisation, auditing and prompt injection 2. Microsoft's Entra Agent ID documentation says traditional identity types "aren't ideal" for agents, and it blocks agent identities from many high-privilege roles 3.
Those efforts cover who the agent is and what it may call. A rail card adds what identity cannot: the one job, the approver, the limits, the evidence and the person who answers for it. It stands beside least-privilege tool access and does not replace it.
The ten fields of a rail card
A rail card is the one-page spec for a job, with ten fields in a fixed order: Job, Trigger, Data scope, Tool scope (read, propose, execute), Output contract, Gate, Limits, Ledger, Evaluation, Owner and kill switch. The table gives the question each field answers, then a weak and a strong answer. The strong answers describe the Segment Drafter.
Scroll horizontally to see all columns.
| Field | Question it answers | Weak answer | Strong answer |
|---|---|---|---|
| Job | What one outcome does this agent produce? | "Help with segmentation." | Draft a segment definition from a plain-English request and return it with counts and reason codes. |
| Trigger | What starts a run, and what never does? | "When needed." | A marketing-operations request routed by the Orchestrator; never on a schedule. |
| Data scope | Which objects and fields may it read, and how masked? | "CRM data." | Segmentation schema, consent-filtered counts and pseudonymised IDs. No direct identifiers, free-text fields or special-category data. No working copies kept. |
| Tool scope | Which tools may it call to read, propose and execute? | "Access to the MCP server." | Read: schema, existing segments, count estimates. Propose: versioned segment draft. Execute: none. |
| Output contract | What must come back, and in what shape? | "A segment." | Draft definition, estimated count, overlap with live segments, reason codes, open questions. |
| Gate | Who approves, on what evidence, and what happens on timeout? | "Someone checks it." | A marketing-operations reviewer, never the requester. Approval binds to the definition hash. A timeout expires the draft. |
| Limits | What caps the damage from one run or one bad day? | "Use sensibly." | Runs per day, budget per run, and an audience size above which a second approver is needed. All set outside the model. |
| Ledger | What does each run record, and who writes it? | "Logging is on." | Correlation ID, request hash, tools called, draft version and hash, counts, approver, outcome, model version. Written outside the agent. |
| Evaluation | How do you know it works, and when do you recheck? | "The demo went well." | Past requests with accepted definitions, plus seeded sensitive-attribute traps. Rerun on any model, prompt or tool change. |
| Owner and kill switch | Who answers for it, and how does it stop? | "The AI team." | Head of marketing operations. An Orchestrator pause, plus an automatic pause after repeated rejections on one request. |
The weak answers share one fault: no system could check them.
A filled rail card: the Segment Drafter
The card below is a filled rail card for the Segment Drafter at L2. Everything in it is illustrative. The tool names, numbers and key names are invented for teaching. It is not a PrivyCDP API, schema or feature.
# Illustrative example only. Tool names, numbers and keys are invented for teaching.
# Not a product API or schema. Replace every value with your own.
rail: segment-drafter
version: "1.0"
level: L2
job: "Draft a segment definition from a plain-English request and return it with counts and reason codes."
trigger: "A marketing-operations request routed by the Orchestrator; never on a schedule."
data_scope:
allowed: [segmentation_schema, consent_filtered_counts, pseudonymised_ids]
excluded: [direct_identifiers, free_text_fields, special_category_data]
working_copies: "none kept after the run"
tool_scope:
read: [example_schema_read, example_segments_list, example_count_estimate]
propose: [example_segment_draft]
execute: []
output_contract: [draft_definition, estimated_count, overlap_with_live_segments, reason_codes, open_questions]
gate:
approver: "marketing-operations reviewer, never the requester"
evidence: [diff_against_live_segments, estimated_count, rule_check_results]
binds_to: definition_hash
on_timeout: "draft expires after 48 hours; never auto-approves"
limits:
runs_per_day: 50
budget_per_run_eur: 0.20
second_approver_above_audience: 2000000
ledger:
writer: "gateway and approval service, never the agent"
fields: [correlation_id, request_hash, tools_called, draft_version, draft_hash, counts, approver, outcome, model_version, card_version]
evaluation:
set: "past requests with accepted definitions, plus seeded sensitive-attribute traps"
metrics: [override_rate, sensitive_attribute_failures_caught]
must_be_refused: [activate_segment, read_free_text_field, use_special_category_attribute]
rerun_on: [model_change, prompt_change, tool_schema_change]
owner: "Head of marketing operations"
kill_switch:
manual: "Orchestrator pause"
automatic: "3 rejected drafts in a row on one request"
Four lines in this example do most of the work.
execute: []means the agent cannot activate anything. Drafting and publishing are separate rails. In the segmentation walkthrough, a separate service re-checks consent and acts only after approval. A bug or a hijack in drafting stops at a draft.binds_to: definition_hashmeans any later edit voids the approval. The reviewer approved these exact contents, not a version of them.on_timeoutstates that a timeout expires. It never approves.must_be_refusedturns the "never" list into tests. Each entry is a call the gateway must refuse and log. A "never" with no test is only a hope.
The 50 runs, the budget, the 48 hours and the audience threshold are placeholders. Set your own, and use words on the card until you have evidence for a number.
Rail card, Agent Card, model card, DPIA: what does each one do?
A rail card restricts one job, while the five documents most often confused with it do other work. "Agent card" is already a protocol term, so the naming trap is real.
Scroll horizontally to see all columns.
| Document | What it does | Covers | Restricts the agent at runtime? |
|---|---|---|---|
| Rail card | Limits one agent doing one job, and names who answers for it | One job | Yes, where systems enforce each field |
| A2A Agent Card | Advertises identity, endpoint, capabilities, authentication schemes and skills for discovery, at /.well-known/agent-card.json 4 | One agent, as others see it | No. It is not a permission system |
| Model card | Reports a model's evaluation results and intended uses 5 | One model | No |
| System prompt | Instructs the model | One session | No. OWASP says a prompt should not be "used as a security control" 6 |
| DPIA | Assesses risk for a processing activity, where GDPR Article 35 requires one 7 | One processing activity | No, though it can set conditions a card carries out |
| AI policy | Sets rules for a team, as in the AI governance policy template | A team or company | No. A card carries out one job's share of it |
Keep all that apply, and link the model card and the DPIA from the rail card. An auditor can then walk from the job to the assessment.
Where is each rail card field enforced?
Each rail card field needs a named system that refuses when the field is broken. A field no system enforces is documentation, and the card should say so. This table is the core of the method, and the test column shows how to prove each control works.
Scroll horizontally to see all columns.
| Field | Enforced by | Test that proves it |
|---|---|---|
| Job | One agent identity per job, plus the Orchestrator's routing table | Send a request for another job. It goes to a person, not to this agent. |
| Trigger | Orchestrator or scheduler | Try to schedule a request-only rail. The start is refused. |
| Data scope | Database view or field projection | Query an excluded field. The view returns nothing. |
| Tool scope | Allow-list in the MCP gateway | Call a tool not on the list. The gateway refuses and logs it. |
| Output contract | Schema validation, plus a number check where figures appear | Return malformed output. It never reaches the reviewer. |
| Gate | Approval service, bound to a hash of the exact payload | Change one character after approval, and the approval is void. Let the requester approve, and it is refused. |
| Limits | Gateway or execution service | Go past the run count or budget. The next run is refused. |
| Ledger | Gateway, approval service and execution service, never the agent | Look for an agent write path to the ledger, and find none. Compare run counts with ledger entries. |
| Evaluation | Test harness in the release process | Change the model with no regression pass. The rail drops a level. |
| Owner and kill switch | Orchestrator or gateway, plus a card register with the owner's name | Drill the stop and time it. Remove the owner and check that the rail drops a level. |
Two design rules sit behind the table. Rules enforce and models explain, so a model's "pass" never overrides a failed rule. And each card should name which Rule of Two properties its session holds 8. A session that reads untrusted text and holds sensitive data gets no state-changing tools, so delivery of a report runs in a separate service, not as a tool the model holds.
How does a rail card map to MCP tool permissions?
A rail card maps to MCP tool permissions through its tool scope field: each verb becomes a set of scopes on one agent identity. The Model Context Protocol leaves this design to you. Its current revision is 2026-07-28, and MCP for Salesforce, HubSpot and your own platform explains what it does and does not guarantee. These steps take a card to a working configuration.
- Give each rail its own agent identity, so the ledger can tell jobs apart and you can revoke one without breaking others.
- Turn each entry under
read,proposeandexecuteinto a named scope, with no wildcards. - Keep the verbs on separate credentials or tool servers, so a propose token cannot call an execute tool.
- Issue short-lived tokens bound to one server. Mint a write token only after approval, in the execution service and never in the model's session.
- Pin each tool's description and schema by hash. A change counts as a new approval and triggers a regression run, because a server can alter a tool description after you approved it 9.
- Treat tool annotations as hints. MCP says clients must treat them as untrusted unless they come from a trusted server 10, so enforce read-only in the gateway.
PrivyCDP's product page describes an MCP-ready interface and an immutable audit ledger that records each AI-assisted action with the human or system actor that authorised it; the rail card itself is a vendor-neutral method, not a product feature.
Who may change a rail card?
Who may change a rail card depends on whether the change narrows or widens what the agent can do. Every change creates a new version.
Scroll horizontally to see all columns.
| Change | Who decides | What they need to see |
|---|---|---|
| Tightening a limit or removing a tool | Rail owner | The reason, and a regression pass if the job could break |
| Widening data scope | DPO | Purpose, fields, masking, and whether the DPIA needs updating |
| Adding a tool or changing a tool schema | Security | Scope, credentials, a Rule of Two check and a regression pass |
| Raising a level | Rail owner, signing off | Written evidence, as set out in rail levels |
| Changing the approver or the owner | Head of the function | The named person, and that the approver is not a requester on this rail |
Each run's ledger entry records the card version, so a reader can tell which rules applied. Store cards versioned next to your segmentation rules, in the customer's own environment, somewhere the agent cannot write to. The Trainer may propose a change, and a person decides it.
How does an auditor read a rail card?
An auditor reads a rail card as the claim and the audit ledger as the evidence. Comparing the two answers three questions.
- Did any run go beyond the card? Compare the tools called and the fields read with the card version recorded on that run.
- Was every execution approved by the right person? Check that the approver was not the requester, that the approved hash matches the executed hash, and that no approval had expired.
- Who changed the card, and was the change tested? Match each new version to its decider in the table above, and to a regression result.
The Policy Drift Checker runs this kind of comparison on metadata, and an owner decides what to do about the findings.
The ledger names approvers because accountability needs a name. Reports drawn from it should still go by rail and role. Annex III point 4(b) of the EU AI Act lists monitoring workers' performance and allocating tasks by individual behaviour as high-risk uses 11, so take advice before using ledger data to rate named staff.
Four common rail card mistakes
Four mistakes make a rail card look complete while leaving the agent uncontrolled. Each has a simple fix.
Scroll horizontally to see all columns.
| Mistake | What it looks like | Fix |
|---|---|---|
| Scope inflation | Fields and tools are added so the agent never hits a refusal at runtime. | Start narrow. Add a scope only for a specific refused call that the job needs. Review unused scopes on a schedule. |
| One card for many jobs | A "marketing assistant" card lists every tool anyone asked for. | Split until each card has one job, one data scope and one approver. |
| No named owner | The owner is "the AI team", or someone who has left. | Name a role and a person. Drop the rail a level when the post is empty. |
| A card nothing reads | The card sits in a wiki while the gateway's real configuration differs. | Generate the allow-list from the card, or check one against the other on a schedule. |
How do you fill your first rail card in a 60-minute workshop?
A first rail card fits a suggested 60-minute workshop with three people: the job's owner, a security engineer and a reviewer who will use the output. Start from a real, low-risk job such as journey QA or a reporting summary.
- Write the job in one sentence. If it needs two outcomes, pick one.
- Write the trigger, and what must never start a run.
- List the fields the job truly needs. Strike anything the last few real examples did not use.
- List tools by read, propose and execute. Default execute to none.
- Define the output so a reviewer can check it without rerunning the job.
- Name the gate: the approver's role, the evidence they see and what a timeout does.
- Set the limits, and say which system enforces each one.
- List the ledger fields and the system that writes them.
- Write the evaluation, with at least one test for each "never".
- Name the owner and how to stop the agent. Then mark each field as enforced or as documentation, and log the gaps.
Run the finished card in shadow mode before anything depends on it.
Browse use casesFunction playbooksAgent roster
FAQ
What should an AI agent permissions policy include?
For one job, it should state the job, trigger, data scope, tools by read, propose and execute, output format, approver, limits, log fields, test set, owner and stop mechanism. A company-wide AI policy sets the rules, and a card applies them to one agent doing one job. Keep the two as separate documents.
Should each agent have its own identity?
Yes. Give each rail its own identity, so logs show which job did what and you can revoke one without breaking the others. A shared service account hides both facts. Microsoft's Entra Agent ID and the NIST concept paper both treat agent identity as its own problem, and practice is still settling.
How is this different from an A2A Agent Card?
An A2A Agent Card is a JSON document that advertises an agent's identity, endpoint, capabilities, authentication schemes and skills, so other software can find it. It describes the agent and does not restrict it. A rail card limits one job and names the approver and owner. An agent can have both.
Who approves changes to an agent's permissions?
The person depends on the change. The rail owner can tighten limits. The DPO approves wider data scope. Security approves new tools and changed tool schemas. Raising a level needs written evidence and owner sign-off. Record each change as a new card version, so the ledger shows which rules applied to each run.
Does one agent need several cards?
Usually, when it does more than one job. One card means one job, one data scope and one approver, so a second scope or approver needs a second card. The Anomaly Watcher holds two levels on one card because both paths serve one job, and the card states each level.
Can we use this with vendor agents we cannot fully configure?
Yes. Fill in the card anyway, and mark each field as enforced by the vendor, enforced by you, or a known gap. HubSpot's agent inbox, for example, lists runs waiting for tool approval 12, so its gate field may be partly covered. Record what you cannot enforce, and let the gaps set the level.
Sources
- OWASP GenAI Security Project, Top 10 for Agentic Applications for 2026 (9 December 2025)
- NIST NCCoE, concept paper "Accelerating the Adoption of Software and AI Agent Identity and Authorization" (5 February 2026)
- Microsoft Learn, "Authorization in Microsoft Entra Agent ID" (opened 1 November 2026)
- A2A Protocol, Agent Discovery
- Mitchell et al., "Model Cards for Model Reporting" (2018)
- OWASP, LLM07:2025 System Prompt Leakage
- GDPR Article 35
- Meta, Agents Rule of Two (31 October 2025)
- Invariant Labs, MCP tool poisoning attacks (1 April 2025)
- Model Context Protocol specification, Tools (revision 2026-07-28)
- EU AI Act, Annex III
- HubSpot Knowledge Base, "Run agents and review output in the agent inbox" (opened 1 November 2026)
- Cycode, list of the OWASP agentic risk names
Back to the AI agent rails hub. For the difference between this card and a prompt or filter, read what AI agent rails are. To write your own, download the rail card template.
This article is general information, not legal advice.
Further reading
- AI Guardrails vs Policies, Prompts
- AI Segment Builder Agent: Segment
- AI Agents for Marketing Operations: A
- Correlation ID — definition
- Agent rails
Published: · Updated:
Editorial dates describe content changes. Confirm current sources before making legal, security or purchasing decisions.