-
-
SIDOM Legajo listo, powered by Craftech
-
A real WhatsApp conversation with the agent on AWS End User Messaging Social: answers grounded in the importer's operations
-
A document reading with the finding assigned to the party that must fix it
-
The supplier conversation over Amazon SES: request in English, reply with PDFs, correction in the same thread
-
A human broker approves the file after a recent sign-in; the agent cannot approve
-
Audit log: every decision with the contact-policy rule that applied
-
Architecture: End User Messaging Social and SES, Bedrock AgentCore (Harness, Gateway, Policy, Memory) and Guardrails, all serverless
Inspiration
In Latin America, a customs broker (despachante de aduana) cannot clear an import until the file (legajo) is complete: commercial invoice, packing list and certificate of origin. The importer or, more often, the foreign supplier holds those documents. The supplier answers in English, in another time zone, by email. Today the broker's staff chase each document by hand: they message the importer on WhatsApp, the importer forwards emails to the supplier, and a gross weight that does not match the invoice, or an unsigned certificate, turns up after the vessel has docked. By then free days at the port are being used up and container demurrage is accruing.
SIDOM, a customs software company in Argentina, asked for an agent that does this chasing: on the channel each party already uses, at the right time for their time zone, telling each party only what they have to do, and never taking the broker's decision away.
What it does
SIDOM Legajo listo is a coordination agent for customs brokerage firms:
- Talks to the importer on WhatsApp, through AWS End User Messaging Social. The importer can simply chat: "hola", "what is missing?", "how is my other shipment going?". The agent answers in seconds, grounded in the operation's data, and remembers each importer's conversation across all their operations. When a milestone before the ETA fires, it sends a template with quick-reply buttons: Upload documents · The supplier will send them · I have a question · Stop notifications.
- Writes to the foreign supplier in English by email (Amazon SES), from an address that belongs to that operation, saying exactly what is missing, what it must match (invoice number, Incoterm) and the deadline in the supplier's time zone. If it is 9 pm in Qingdao, the email waits until 9 am Qingdao time.
- Reads every PDF through an external document reader behind an OpenAPI contract. The agent never does OCR itself. When the reader reports a finding (for example a gross weight of 12,480 kg against 12,840 kg on the invoice), the agent decides who has to fix it, asks the supplier in the same email thread, and tells the importer "you don't need to do anything".
- Answers the importer's questions from the firm's checklist. Out-of-scope questions (tariff classification, customs valuation, duties, legal advice) are blocked by Amazon Bedrock Guardrails, answered with a fixed reply and handed to the broker.
- Reschedules when the ETA moves. A carrier event reschedules every milestone deterministically and the agent tells each party the new deadline.
- Lets a human take over at any time, and never approves: a broker reviews the documents, the readings and each finding, then approves after a recent sign-in. No tool of the agent can approve.
- Audits every decision with the rule that applied (DENY/DEFER per contact-policy rule, zero violations) and labels every KPI with its N and source.
What is real and what is simulated
| Real in the deployed stage | Simulated | Data |
|---|---|---|
| Every AWS service. Amazon SES end to end (sending and receipt rules). AWS End User Messaging Social with the firm's own WhatsApp Business account, live for the registered demo phones. Amazon Connect number and Amazon Transcribe for Meta's verification call. Amazon Bedrock AgentCore Harness, Gateway, Policy and Memory, Bedrock Guardrails, EventBridge Scheduler, SQS, Lambda, DynamoDB, S3, GuardDuty, Cognito, CloudFront and WAF | The importer's phone in public trial worlds (an in-console phone simulator that enters through the same adapter); the suppliers' mailboxes (real SES email to mailboxes on our own domain, answered by a supplier simulator); the document reader and the customs-management platform (mocks behind real contracts); a paused clock per world | 100% synthetic |
How we built it
- Agent: Amazon Bedrock AgentCore Harness running Claude Sonnet 5.5 through a tagged application inference profile. Each event on a file (an importer message, a supplier email, a document reading, a milestone, an ETA change) produces one agent turn, serialized per file through an SQS FIFO queue and deduplicated per event. Before invoking the model, the worker preloads the reads every turn needs (the operation, the file, the importer's last ten operations and the checklist) through the same fenced tool code, so a WhatsApp reply takes two model calls instead of five.
- Tools: 16 tools behind an AgentCore Gateway (MCP, IAM auth), across 5 Lambda targets. AgentCore Policy (Cedar) fences what the model can do: email only to suppliers, WhatsApp only to importers, no approval tool at all. Every tool takes a signed, short-lived session token; the Lambda derives the file, importer and supplier from it, never from the model's input, and validates with
zod.strict(). - Memory: AgentCore Memory keeps one conversation per importer across operations, plus long-term preferences and facts with an exclusion instruction (no IDs, bank data, amounts or document contents).
- Guardrails: G1 filters untrusted input before the model sees it (denied topics, prompt attacks, masking of tax and bank ids). G2 checks every outgoing text with contextual grounding against the tool results of that turn and relevance to the importer's question. A deterministic verifier checks that every date, weight and number in an outgoing text comes from those results, and that no message contains a foreign link.
- Channels: AWS End User Messaging Social (
SendWhatsAppMessage; inbound messages, media and statuses through SNS; read receipt and typing indicator). Amazon SES v2 for sending (configuration-set events through EventBridge) and receipt rules ‚Üí S3 ‚Üí Lambda for replies, trusted only withdmarcVerdict PASSfrom the registered supplier contact. The WhatsApp number is an Amazon Connect phone number declared in code; a contact flow records Meta's verification call and Amazon Transcribe reads the code. - Time: every deadline is an EventBridge Scheduler schedule. Each trial world has its own paused clock, so a week-long story plays in minutes with Advance to the next event.
- Stack: SST v4, serverless only, all infrastructure as code. TypeScript monorepo, React 19 + Vite + Tailwind v4 console, tRPC v11 BFF on Lambda, Cognito. Deployed only by GitHub Actions with OIDC. 3,054 unit and local-flow tests, 472 UI tests (Playwright), a scenario runner against the deployed stage, and agent tests on a local model before anything reaches Bedrock.
Pre-existing work disclosure. The repository skeleton (SST and CI setup, CI bootstrap template, lint scripts, console shell and shared components, Cognito sign-in, tRPC base, logging, retry and crypto helpers, landing gallery, AgentCore setup patterns, agent definitions in .claude/) was reused from internal Craftech scaffolding built before the contest period. Process skills in .claude/skills/ come from mattpocock/skills (development tooling, not product code). Everything specific to this product was built during the Submission Period.
Challenges we ran into
- Trusting nothing that arrives. Emails, WhatsApp messages and PDFs are hostile input. Untrusted content reaches the model escaped, inside a delimiter with a random suffix per turn, so an email cannot close the block and forge an event. PDF metadata, subjects and file names never reach the model.
- A 31-second WhatsApp reply. Measuring the first live turn showed the time was not the model: the Harness runs a response's tool calls one after the other, and two outgoing texts were refused by the grounding guardrail because "hola" is not a question. We moved the reads before the model call and scored small talk against the operation's status. A reply now takes about 15 seconds. The refused turn also taught the agent's memory not to answer greetings, so the prompt now states that every importer message gets an answer, whatever the conversation concluded before.
- A WhatsApp number without a SIM. Meta verifies a number with a phone call. An Amazon Connect number, a contact flow that records the call and Amazon Transcribe read the code automatically, with a person taking over after three failed calls.
- Keeping the model away from actions it must not take. Cedar rules need
hasguards on every field they read; tool schemas are generated from zod and tested against every rule. - Time zones and business hours. A request that is fine at 10:30 in Buenos Aires is rude at 21:00 in Qingdao. Contact policy (hours, one reminder per day, opt-out, the 24-hour WhatsApp window) lives in code, not in the prompt.
Accomplishments that we're proud of
- A real WhatsApp conversation with the agent on AWS End User Messaging Social, answering in 14 to 26 seconds, with memory across the importer's operations.
- A real email loop with the supplier (request, reply with PDFs, correction in the same thread, bounce handling) on Amazon SES.
- An agent that cannot approve a file, leak a link or write to the wrong party, even when a prompt injection asks it to; the policy log shows the DENY decisions, with zero violations.
- Everything as code, including the WhatsApp number, deployed only by CI.
What we learned
- Agentic does not mean autonomous everywhere. The model is best at deciding what to say to whom; identity, recipients, deadlines, approvals and contact policy are safer in deterministic code around it.
- Latency in an agent is mostly round trips. Reads the code can predict belong before the model call, not inside the loop.
- An agent's memory also remembers its mistakes; rules that must always hold have to say they win over the conversation.
What's next for SIDOM Legajo listo
- Pilot with customs brokerage firms in Argentina, with Meta's approved templates and the firm's own WhatsApp number.
- Plug the document-reader and platform contracts into SIDOM's customs-management platform instead of our mocks.
- More documents (bill of lading, insurance, licenses) and more countries in Latin America.
Built With
- amazon-bedrock
- amazon-bedrock-agentcore
- amazon-bedrock-guardrails
- amazon-cloudfront
- amazon-cognito
- amazon-connect
- amazon-dynamodb
- amazon-eventbridge
- amazon-guardduty
- amazon-ses
- amazon-sqs
- amazon-transcribe
- amazon-web-services
- aws-end-user-messaging-social
- aws-lambda
- cedar
- claude
- github-actions
- playwright
- react
- sst
- trpc
- typescript
- zod
Log in or sign up for Devpost to join the conversation.