Inspiration

When someone can't make a shift, a coordinator loses the morning to chat threads. They confirm which shift is affected, find who is qualified and free, chase replies, check nobody gets booked twice, and forward scattered notes to whoever picks up the work. The work is urgent, repetitive and easy to get wrong, and it happens on a phone, not in a dashboard. So we built an agent that does it where people already are: WhatsApp.

What it does

OutToday is an AI agent on WhatsApp that turns "I can't work today" into confirmed cover.

  1. Report. Ana texts "I can't make tomorrow morning". The agent finds her exact shift and asks her to confirm it with a button. It never asks why she's absent, and it stores no medical detail.
  2. Approve. The manager sees the impact and who is eligible, with a reason for every exclusion (for example "Taylor: already booked"). One click starts a bounded search.
  3. First accept wins. Eligible backups get a WhatsApp offer. If two of them tap Accept in the same second, exactly one assignment is committed, and the other person is told kindly.
  4. Cited handover. Ana's notes become a handover brief in which every claim quotes its source verbatim, and unknowns are flagged instead of guessed. The manager reviews and publishes it, and the backup acknowledges it in WhatsApp.
  5. Proactive check-in. When someone shows no work activity after their shift starts (from tools such as Teamwork, Jira, GitHub, Slack or an HR system), OutToday checks in on WhatsApp. If there's no reply it sends an RCS nudge, then alerts the manager. Silence never turns into an absence on its own, and approved leave from the HR system skips the check-in.

Managers work in a web console: cases, people, teams, schedules, channels and tool connections, with in-app setup guides for each connector.

How we built it

AWS Communication Developer Services, all called at runtime

  • WhatsApp: AWS End User Messaging Social (socialmessaging.SendWhatsAppMessage). Inbound messages and delivery statuses arrive through SNS, then SQS with a dead-letter queue, then a router Lambda.
  • Email: Amazon SES (sesv2.SendEmail) for manager alerts, client notices and invitations, through a configuration set that publishes delivery events to EventBridge. The domain is authenticated with DKIM, SPF and DMARC.
  • RCS: AWS End User Messaging SMS and Voice v2 (SendRcsMessage) for the check-in fallback.

The agent

  • A Strands agent on Amazon Bedrock AgentCore Runtime.
  • Claude Haiku 5.5 handles intake and clarification. Claude Sonnet 5.5 writes the cited handover brief.
  • Every agent output is a typed, validated model. A brief can't leave draft until every citation passes a verbatim-quote check against the source material.
  • The model never chooses who is acting. Tools get the caller's identity from code, and their schemas have no identity fields. Only deterministic command handlers write data.

Guarantees in code

  • Every change goes through a versioned command in DynamoDB. Replays return the cached result.
  • Accepting an offer is one conditional TransactWriteItems over per-person 30-minute slots, so double-booking can't happen. A race test fires parallel accepts and expects exactly one winner. Our production canary runs the same path and reports one winner.

Workflows and integrations

  • Step Functions runs the check-in ladder. EventBridge Scheduler handles offer deadlines and a 15-minute shift sync from scheduling tools (iCal, Deputy, When I Work).
  • 15 connector kinds read activity, sign-ins, leave and shifts. They can also push signed webhooks out when a case changes.
  • People's own Microsoft 365 and Google calendars also sync, read-only through OAuth, as their meetings (private events show as Busy). Each scheduling connection has Sync now, and the Schedule page has a Sync button.

Console and delivery

  • React on CloudFront, Cognito sign-in with Google, Microsoft or email, an HTTP API, and AppSync Events for live updates.
  • Everything is defined in AWS CDK. A signed Gitea webhook starts AWS CodePipeline, which runs the full test suite (pytest in 24 parallel shards) and deploys to production in about 10 minutes.

Challenges we ran into

  • Model behaviour. Haiku rejected conversations that ended on an assistant turn, and failed on thinking-block signatures. We fixed both: the runner continues with a short user message, and thinking is turned off for that model. Haiku also repeated injected text in briefs during our evals, so the brief moved to Sonnet.
  • Trusting the model without trusting it. Making identity, tenant and authority impossible for the model to set took more design work than any prompt.
  • Delivery plumbing. Mirroring our Gitea repository into AWS through an IAM user was blocked by the organisation's policies. We replaced it with a signed webhook that fetches the code with a read-only deploy key, so no long-lived AWS keys exist outside the account.

Accomplishments that we're proud of

  • Exactly one assignment per shift, proven by a concurrency test in CI and by a canary in production.
  • A brief can't cite text that doesn't exist.
  • Three AWS Communication Developer Services, each used for the job it fits best.
  • Measured in our eval suite (live Bedrock, synthetic cases): intake passed 32 of 32 cases (p50 latency 5.2 s), and the Sonnet handover brief passed 9 of 10 (p50 10.4 s).

What we learned

  • Deterministic commands around a small, well-typed agent beat a large autonomous agent for anything that commits money or people's time.
  • Evals catch model regressions that unit tests never will. Running them on every prompt or model change is what let us pick the right model per task.

What's next

  • A pilot on one Scopic support rotation.
  • Microsoft Teams and Entra ID sign-in signals.
  • Voice-note intake.

Disclosures

  • Pre-existing work: an October 2026 clickable HTML prototype and planning documents informed the design. No prototype code was reused.
  • Third-party services: Meta WhatsApp Business Platform (through AWS End User Messaging Social), Google sign-in, and the APIs of the connected work tools.
  • Data: every person and case in the demo is synthetic.
  • AI assistance: we used Claude Code during development.

Built With

Share this project:

Updates

Submission history