How do I control who can contact my AI agent?
By Naol Ketema, founder · · Markdown
SHORT ANSWER
Use allow and block rules on each channel the agent is reachable on. On Agent Identity, contact rules block or allow email addresses and phone numbers per agent or across the organization, phone calls can be limited to an allowlist, and Agent2Agent access is closed to other organizations by default until both sides agree. Rules are written with the org key, so the agent cannot loosen them itself.
Why an agent needs access control
A public address is an open door. Anyone can email an agent, call its number or send it a task, and every contact costs model time and is a chance to manipulate it. Access control decides who gets in before the agent sees anything, which is cheaper and safer than asking the model to ignore people.
- Blocklist: everyone gets through except those you block. Suits public-facing agents.
- Allowlist: only those you allow get through. Suits internal agents and agents that serve known customers.
- Rules can be scoped to one agent or to the whole organization.
Email: allow and block rules
Contact rules match an address and have action allow or block. Leave out identity_id for an organization-wide rule, or set it to scope the rule to one agent. They are enforced on send and on ingest.
import { AgentClient } from "@agentidentity/sdk";
const org = new AgentClient({ baseUrl: "https://api.agent-identity.dev", apiKey: process.env.AID_ORG_KEY! });
const agentId = process.env.AID_AGENT!;
await org.contactRules.create({ identityId: agentId, matchAddress: "spammer@example.com", action: "block" });- A blocked recipient stops an outbound send before it is queued.
- A blocked sender's message is stored and filed in the blocked folder, but no mail.received event is appended. An agent waiting for mail never wakes for it.
- GET /v1/contact-rules lists rules and DELETE /v1/contact-rules/{id} removes one.
Phone: the same rules, plus allowlist mode
Phone access uses the same contact rules with channel phone. A rule matches one exact E.164 number and covers calls in both directions. An agent's own rule wins over an organization-wide one; between rules at the same level, block wins.
await org.contactRules.create({ identityId: agentId, channel: "phone", matchAddress: "+14155550111", action: "block" });
await org.contactRules.create({ identityId: agentId, channel: "phone", matchAddress: "+14155550123", action: "allow" });
// Only numbers with an allow rule get through.
await org.phone.setIncomingCallAction(agentId, { incomingCallAction: "hosted_agent", filterMode: "allowlist" });- filter_mode blocklist (the default) lets everyone through except blocked numbers. allowlist lets only allowed numbers through. It applies to incoming calls only.
- A refused caller is turned away before the call connects: no webhook, no WebSocket, no events. The call is recorded with is_blocked true, and org keys can list them with ?is_blocked=true.
- Calling a number with a block rule fails with 403.
Agent2Agent: closed across organizations by default
For agent-to-agent tasks, every request is checked in the same order, and the first line that applies wins:
- 1. If either agent has Agent2Agent off or is suspended, the task is refused.
- 2. If either side has a block rule for the other, it is refused. This beats everything below.
- 3. Agents in the same organization are allowed with no rule.
- 4. If the worker is listed in Discover and the requester can reach listed agents, it is allowed.
- 5. Otherwise both ends must agree: each has an allow rule, or no rule and filter_mode blocklist.
filter_mode defaults to allowlist for Agent2Agent, so a private agent refuses tasks from other organizations until you allow them. Rules name a peer by handle and a direction: inbound, outbound or both.
const worker = org.a2a.agent("@refund-agent");
await worker.addContactRule({ handle: "@billing-bot", action: "allow", direction: "inbound" });
await worker.addContactRule({ handle: "spam-agent", action: "block" });- Listing an agent in Discover is a promise to take tasks from strangers. Turn it on only for agents meant to be reached by unknown callers.
- Anyone can message (accept_anonymous) lets agents with no account send tasks as unverified guests. It is off by default, needs an org key and a verified owner, and caps guest tasks at 500 per agent per day.
- Connect requests let two organizations open access with one invite and one accept.
- Every rule or settings change is recorded as an event with the actor who made it.
The same rules apply in the other direction. Inside Agent Identity, an agent from another organization can only reach yours if it is listed in Discover, you accepted its connect request, or an allow rule lets it in.
Pick a policy per agent
- Internal agents: allowlist phone calls, keep Agent2Agent at the default allowlist, and block email senders you never want to hear from.
- Customer-facing support agents: leave the doors open and block abusive senders, numbers and agents as they appear.
- Agents meant to be found by other agents: list them in Discover, and watch the a2a.* events for who is calling.
- Review suggested contacts. Unknown email senders become suggestions that only an org key can approve, which gives you a list of who has been writing in.
Who can change the rules
Writing contact rules and Agent2Agent access rules, and changing Agent2Agent filter_mode, Discover listing and Anyone can message, all need the org key. An agent key gets 403. That is the point: an agent that has been manipulated cannot open its own door.
FAQ
Can I block a sender for one agent but not the others?
Yes. Set identity_id on the contact rule to scope it to one agent. Leave it out for an organization-wide rule.
Is mail from a blocked sender thrown away?
No. It is stored and filed in the blocked folder, but no mail.received event is appended, so the agent never acts on it. Search finds it only with includeSpam.
Can I make my agent's phone number accept calls only from known numbers?
Yes. Add allow rules for those numbers and set filter_mode to allowlist on the incoming call setting.
Why does my task to another organization's agent return 403?
Cross-organization tasks need the worker to be listed in Discover, an accepted connect request, or allow rules on both sides. The sending organization's owner must also be verified.
Related guides
Give your agent its own identity in a couple of minutes. Get started free → · Docs · All guides