Allowlist and denylist rules for agent email, backed by Lists Nylas introduced a dynamic allowlist and denylist system for AI email agents using Lists and Rules, decoupling policy from application code. Lists are editable collections of domains or addresses that Rules reference via the in_list operator, enabling non-engineers to update policies without redeployment. The system supports both inbound and outbound filtering, with a fail-closed approach on transient errors. The usual way to keep an AI email agent from talking to the wrong people is a hardcoded set in your application code: ALLOWED DOMAINS = {"yourcompany.com", "customer.example"} That works, and for a single internal agent it's the right call. But the moment a non-engineer needs to add a customer domain, or you want the same allowlist to govern five different agents, or you want it to apply to mail coming in and not just going out , that set in code becomes a deploy-shaped bottleneck. Every change is a PR, a review, a release. There's a layer below your code that can carry that policy for you. An Agent Account on Nylas evaluates Rules against every message — inbound on arrival, outbound on send — and those rules can point at Lists , which are typed, editable collections of domains, TLDs, or addresses. Update a list, and every rule that references it picks up the change immediately. No redeploy, no code change, no model in the loop. This post goes deep on that pattern: Lists fronted by the in list rule operator, used for allow and block on both directions. If you've already read the basic inbound/outbound filtering post, this is the part that makes the filtering dynamic. The data plane doesn't change. An Agent Account is just a grant with a grant id , and everything you already know about Messages, Drafts, Threads, and Folders still applies. Rules and Lists sit one level up, on the control plane — they're application-scoped admin resources with no grant ID in the path. Your API key identifies the application, and the rules apply to every Agent Account in a workspace. So the mental model is two planes: GET /v3/grants/{grant id}/messages , nylas email send , the stuff your agent does. POST /v3/lists , POST /v3/rules , the stuff that decides what the agent is A List holds values. A Rule references a list through the in list operator and says "if the sender domain is in this list, block it" or assign it, or archive it . Change the list, and the rule's behavior changes with it. That indirection is the whole point: the what which domains lives in a list a human can edit; the how block vs. route lives in a rule you set once. A few honest tradeoffs, because a static ALLOWED DOMAINS set genuinely is simpler when you only have one agent: message.created webhook — so your application never even sees it. block rule can't evaluate a list lookup because of a transient error, Nylas blocks the message rather than letting it slip through. Inbound gets a 451 tempfail so the sender retries; an API send gets a retryable 503 .The flip side: if your agent legitimately needs to reach arbitrary external recipients — an open-ended sales tool, say — a static allowlist will block valid sends and frustrate the workflow. Lists fit internal and known-customer agents, not cold outreach. For that case, lean on volume caps and human approval instead, which the restrict agent recipients https://developer.nylas.com/docs/cookbook/agents/restrict-agent-recipients/ cookbook recipe covers. You need an Agent Account a grant created via POST /v3/connect/custom against a registered domain — see Agent Accounts https://developer.nylas.com/docs/v3/agent-accounts/ , an API key for the same application, and the host in your examples set to https://api.us.nylas.com . Every API call below carries Authorization: Bearer