Zum Hauptinhalt springen
Back to Blog
Guides

Designing app-level policies for humans and AI agents

A practical guide to per-route policies for people, AI-assisted users and agents: allow, adapt, challenge, review or limit, with clear fallbacks and risk tiers.

Toshendra Sharma

By Toshendra SharmaFounder & CEO, AgentCredia · Published November 12, 2026

Designing app-level policies for humans and AI agents
November 12, 2026
11 min read
#Guides#AI Agents#Application Policy#API Design#MCP

Good app-level policies for humans and AI agents are written per route and per risk tier, use five actions (allow, adapt, challenge, review and rate-limit), and branch on both the actor class and the basis behind it. Every route gets an explicit fallback for Unknown and for timeouts, rollout starts in observation mode, and authorization stays with your existing credentials.

Applications used to make one assumption about who was on the other end: a person, clicking. That assumption no longer holds. The same interfaces now serve people, people working alongside AI assistants, and autonomous agents acting on someone's behalf. Each of these can be legitimate, and each can deserve a different experience.

This guide is about the decision layer: how to turn actor context into application behavior that is precise, safe and easy to reason about. It applies whether you run a SaaS product, a public website, an API or an MCP server. For a summary of the approach, see AI agent access policies.

Start from the decision, not the detector

Teams often begin by asking how to detect agents. A more useful question is what your application should do differently once it knows more about who is acting. If the answer is "nothing", you do not need a policy for that route. If the answer is "serve a structured response", "add review" or "apply a different limit", you have found a place where actor context creates value.

Thinking in decisions also keeps the scope honest. A policy can only be as precise as the evidence behind it, so you design the decision first and then ask what evidence it needs.

The five actions

Most useful policies reduce to five actions. Blocking exists, but it is the bluntest tool and usually not where you should start.

Allow

Proceed as normal. This is usually the right action, including for much agent traffic. Many automated clients are welcome: assistants fetching documentation for a user, integrations reading a catalog, monitoring tools checking status.

Adapt

Serve a different experience suited to the actor. A verified agent might receive a structured JSON response or a Markdown version of a page instead of a heavy HTML interface. A user who disclosed AI assistance on a support ticket might have it routed with that label so the right team picks it up. Adapting is often the most valuable action because it improves the experience for everyone rather than restricting anyone.

Challenge

Ask for something stronger before continuing: re-authentication, a confirmation step, or an API credential with the right scope. Challenges belong on actions with real impact, and they should rely on controls you already trust. The actor result helps decide when to apply them, not whether they work.

Review

Queue the interaction for a person to look at, without blocking the user in the meantime where that is acceptable. Review suits workflows where a mistake is costly but delay is tolerable, such as large data exports or changes to account ownership.

Rate-limit

Apply limits that fit the actor and the route. A verified crawler might get a generous limit on read-only routes. Unknown clients get your standard limit. Limits protect capacity and are easy to reverse, which makes them a safe early enforcement step.

Classify your routes by risk tier

A policy that is right for a pricing page is wrong for a password change. Group your routes into tiers and design each tier separately.

  • Public and read-only. Marketing pages, documentation, public catalogs. Actor context mostly drives adaptation and rate limits. There is little reason to challenge anyone here.
  • Authenticated, low impact. Dashboards, search, viewing records. Actor context helps you understand usage and tailor the interface. Enforcement is light.
  • Authenticated, high impact. Changing credentials, exporting data, deleting resources, inviting members, creating orders. Existing controls stay in place for everyone. Actor context informs when to add review or a challenge, and is recorded for analysis.
  • Machine interfaces. APIs and MCP tools. Here identity evidence from the client, such as a validated request signature, can grant structured access, while scope-of-action authorization continues to come from your credentials. On MCP servers over HTTP, for example, the MCP authorization specification has the server validate an OAuth access token on every request and return insufficient_scope when a tool needs more.

Writing down the tier for each route is the single most useful exercise before any enforcement.

Respect the basis of each result

An actor class is only as strong as the evidence behind it. A useful result states its basis:

  • Verified: a checkable assertion validated, such as a request signature against a published key under RFC 9421, or a crawler IP confirmed through the operator's documented method, as Google and Microsoft Bing describe for their crawlers.
  • Declared: the client or your own application stated it, such as a self-declared client name or an AI-assistance disclosure in your UI.
  • Inferred: a conclusion from behavioral or contextual signals.
  • Unknown: the evidence does not support a determination.

Policies should use the basis, not just the class. Granting structured access to a verified agent is reasonable. Granting the same access to a client that merely declares itself an agent is a different decision, and your policy should say so explicitly.

One more distinction matters a great deal. A validated agent signature authenticates a key and the identifier it is associated with; the charter of the IETF Web Bot Auth working group is about cryptographically authenticating automated clients, which is a different question from authorizing what they do. Our guide on verifying signed agent requests covers the checks. It does not prove that a person authorized the action, or that the action is safe. Authorization still comes from your own credentials, scopes and business rules.

Fallbacks: Unknown, timeouts and missing evidence

Every route needs an answer for the cases where the actor result does not help.

Unknown

When the evidence does not support a class, the result is Unknown, and the route's fallback applies. Our guide on handling unknown traffic goes deeper on choosing it. Unknown should never be treated as Human by default, and it should not be treated as malicious either. For most routes, the fallback is simply the behavior you would apply without actor context.

Timeouts and errors

Classification sits in the request path, so you must decide what happens if it is slow or unavailable. This is the classic fail-open versus fail-closed choice, and it belongs to the application owner, per route:

  • Fail open: the request proceeds as it would without classification. Right for public pages, read-only APIs and most low-impact actions, where availability matters more than precision.
  • Fail closed: your existing stronger control applies, such as re-authentication or review. Right for high-impact actions where you already have a safe default path.

Note that failing closed does not mean blocking. It means taking the conservative path your application already supports.

Stale evidence

Evidence has a time and scope. A classification from the start of a session should not be reused for a sensitive action later in that session without fresh evidence. Tie high-impact decisions to evidence gathered for that action.

A policy table you can reason about

Keeping policy as data rather than scattered conditionals makes it reviewable and testable. Here is an illustrative shape in TypeScript:

TS
type ActorClass = "human" | "human_ai" | "agent" | "unknown";
type Basis = "verified" | "declared" | "inferred" | "unknown";
type Action = "allow" | "adapt" | "challenge" | "review" | "rate_limit";

interface Rule {
  actor: ActorClass | "*";
  basis?: Basis[];
  action: Action;
}

interface RoutePolicy {
  tier: "public" | "auth_low" | "auth_high" | "machine";
  failMode: "open" | "closed";
  rules: Rule[];
  fallback: Action; // used for Unknown, timeouts and anything unmatched
}

const policies: Record<string, RoutePolicy> = {
  "GET /docs/:page": {
    tier: "public",
    failMode: "open",
    rules: [{ actor: "agent", basis: ["verified", "declared"], action: "adapt" }],
    fallback: "allow",
  },
  "GET /api/v1/catalog": {
    tier: "machine",
    failMode: "open",
    rules: [{ actor: "agent", basis: ["verified"], action: "allow" }],
    fallback: "rate_limit",
  },
  "POST /account/export": {
    tier: "auth_high",
    failMode: "closed",
    rules: [{ actor: "agent", action: "review" }],
    fallback: "challenge",
  },
};

function decide(route: string, actor: ActorClass, basis: Basis, timedOut: boolean): Action {
  const policy = policies[route];
  if (!policy) return "allow";
  if (timedOut) return policy.failMode === "open" ? "allow" : policy.fallback;
  const rule = policy.rules.find(
    (r) => (r.actor === "*" || r.actor === actor) && (!r.basis || r.basis.includes(basis)),
  );
  return rule ? rule.action : policy.fallback;
}

A few properties make this shape work well. Every route states its tier and fail mode. Rules that grant special treatment require a specific basis. Unknown and unmatched cases always land on an explicit fallback. And because it is data, you can review it in a pull request, test it, and log which rule fired for each decision.

Roll out in observation mode first

The safest way to introduce actor-aware policies is to not enforce them at first.

  1. Observe. Record classifications and the decisions your policy would have made, without changing any behavior.
  2. Compare with ground truth. Check results against outcomes you already know: internal test traffic, known integrations, accounts you have verified through other means, incidents you have already investigated.
  3. Measure the right things. Look at coverage, the unknown rate per route, false positives against known outcomes, and added latency. A route with a high unknown rate is not ready for enforcement based on actor class.
  4. Enforce one route at a time. Start with reversible actions such as adapting responses or adjusting rate limits. Move to challenges and review on high-impact routes only when the evidence supports it.
  5. Keep watching. Clients change, standards evolve and new agents appear. Keep the observation data flowing after enforcement starts.

Guardrails for decisions about people

Actor context is excellent for shaping experiences, routing traffic and focusing review. It is the wrong tool for making consequential decisions about individuals on its own.

Do not use an inferred actor class as the sole basis for decisions about employment, credit, insurance, housing, education or access to essential services. Do not present a Human result as verification of someone's identity. Do not treat a disclosed use of AI assistance as wrongdoing unless your own rules for that workflow say so and your users know it. Where people are affected, keep a person in the loop and give them a way to resolve mistakes.

These guardrails are not only about fairness. They also keep your policies stable, because decisions that rest on strong evidence and clear rules are the ones you will not need to unwind later.

Where Proof of Actor fits

Proof of Actor is built for this decision layer. Detect gathers the signals available to your integration and labels each result with its basis. Understand shows trends, evidence and the unknown rate by route, so you can see where your policies have solid ground. Route applies the policies your team writes, with explicit fallbacks for Unknown and timeouts and a fail mode you choose per route. Results use four classes, Human, Human + AI, Agent and Unknown, and every team starts in observation mode. Enforcement is always the application owner's decision.

To see how the flow fits into a request, read How It Works. If you operate an application, website, API or MCP server and want to design policies like these with us, apply for early access.

Sources

Key Takeaways

  • Write policies per route and per risk tier, not one global rule for all automated traffic.
  • Use five actions: allow, adapt, challenge, review and rate-limit. Blocking is rarely the right first move.
  • Decide fail-open or fail-closed per route, and give Unknown and timeouts an explicit fallback.
  • Start in observation mode, compare results with outcomes you already know, then enforce one route at a time.
  • Never let an inferred actor class alone make a consequential decision about a person.