Create a key to copy examples filled with your team.
Build an AI agent inbox on PostShiba
Give an agent a real inbox with signed webhooks and reply support.
PostShiba receives and parses the mail. Your application decides what the agent may read, which model to call, and whether a reply is safe to send. Keep those responsibilities separate so untrusted mail cannot bypass your model and reply policies.
The setup in this guide uses a hosted PostShiba inbox. Hosted inboxes skip MX setup, but PostShiba only routes them after your approved team has an active shared-IP cluster. You also need a verified sending domain and tenant credential before the agent can reply.
Prepare the shared cluster
Create the cluster before you issue an inbox. Wait until its response reports sending_ready: true.
PostShiba must approve the team first. Cluster and inbox creation return 403 {"error":"kyc_required"} until then.
Pick an inbox model
Use one inbox per agent when agents have different owners, tools, or permissions. Each inbox has its own secret and can be disabled on its own.
Use one inbox with plus-addresses when every conversation shares the same trust boundary. For example, inbabc123+conversation_42@inbound.postshiba.com lands in the inbabc123 inbox and sets thread_id to conversation_42.
Tenants are the stronger boundary inside one PostShiba team. If your product serves several customers, create one tenant per customer and put that customer's domains, credentials, inboxes, and suppressions under it.
1. Create a tenant when you need isolation
You can skip this step for a single internal agent and use the team's default tenant.
The shell examples share these variables. Run the exports in your current shell, or put them in setup.sh and load that file with source setup.sh.
Keep the returned tenant ID and slug. The ID provisions tenant-owned resources. The slug is convenient on send requests and appears as tenant_id in delivery webhook payloads.
2. Issue a hosted inbox
Your team must pass PostShiba's sender review before it can create an inbox. The API returns kyc_required until then.
Omit sending_domain_id and local_part. PostShiba generates an address on its inbound zone.
The result is ready to receive:
Save the inbox ID, address, and webhook_secret with your agent record. PostShiba omits the secret from inbox lists.
Production webhook URLs must use HTTPS. Use a public address. At delivery, PostShiba rejects localhost, metadata.google.internal, IPv4 private and link-local ranges, and IPv6 loopback and link-local ranges.
3. Verify and store every webhook
An email is untrusted input. Verify the signature, reject stale timestamps, deduplicate on the inbound message ID, and copy the message into your database before a model sees it.
Do not run the model inside the webhook request. PostShiba's webhook client waits ten seconds for a response. A slow model call causes a retry and may run the same agent task twice.
upsertInbound must use the PostShiba message ID as its unique key. enqueueOnce must keep a durable deduplication key. If queue publication fails, let the request fail so PostShiba can retry both safe steps.
The five-minute age limit is your receiver policy. PostShiba signs the timestamp but does not enforce a replay window for your application.
4. Put a safety step before the model
The email body can contain prompt injection, malicious links, or instructions to use tools. It should never become a system prompt.
After the policy check, pass only approved inputs to the model and either save or send its draft:
Your application owns policy and model. PostShiba neither runs agents nor inspects prompts. One inbox can feed a human approval queue, a read-only summarizer, or an agent with a limited set of tools.
Start with no automatic tool calls and human approval for replies. Add autonomy per sender or workflow after you have logs and failure handling.
5. Send the agent's reply
A hosted inbox receives mail, but it is not a sending identity. Verify a sending domain, create a shared cluster, and issue an SMTP credential for the tenant first. The transactional email guide shows those three setup calls. Adapt its domain and credential requests by setting tenant_id to this inbox's tenant.
Send with the platform token. Set reply_to to a plus-address so the next inbound message carries your conversation ID in thread_id.
queued: true means at least one recipient was accepted by the injector. Send one recipient per request when the agent needs a clear delivery result for each conversation.
Use the delivery webhook to move the reply through processed, delivered, deferred, bounce, dropped, or spamreport in your UI. Match agent_id and conversation_id from unique_args.
6. Recover missed work by polling
PostShiba stores inbound mail for a configurable retention window. The default is 168 hours. Read retention_hours from the inbox and expires_at from each message. Polling is useful after downtime or when a queue publish fails.
PostShiba has no replay action for dead inbound deliveries. Poll before the message expires.
The list returns at most 200 live messages, newest first. Fetching one message also returns its raw MIME and base64 attachment bytes.
Do not rely on PostShiba as long-term agent memory. Copy messages and attachment metadata into your own storage as they arrive.
Agent safety checklist
- Keep the platform token on your server. Do not give it to the agent or browser.
- Use lowercase, email-safe conversation IDs in plus-addresses.
- Give each inbound message ID a unique database constraint.
- Verify the raw body before JSON parsing.
- Queue model work and return
2xxafter the durable write. - Treat HTML, links, attachments, and quoted text as untrusted.
- Keep tool permissions outside the email and outside the model's response.
- Put a human in the loop for money movement, account changes, data deletion, and first contact with a new sender.
- Record the prompt inputs, decision, tool calls, reply, PostShiba
message_id, and delivery events. - Disable an agent's inbox with
DELETE /api/v1/inboxes/:idwhen you retire it.
The API cannot change an inbox webhook after creation. Use the PostShiba dashboard to update its URL or format.