Inspiration

For years, my agency has worked with MA-Events GmbH, an event agency that produces corporate events, galas and conferences.

A large event is a promise that twenty companies make at the same time. The agency sells it, but the stage, the catering, the light, the shuttle, the venue and the client each hold their own piece of it - and their own phone.

Then, two hours before doors open, the truck with the stage gets stuck in traffic for sixty minutes. The stage crew writes it into a WhatsApp group. The producer reads it between two calls. Now someone has to work out what moves: the soundcheck, the catering, the doors. Someone has to decide whether the overtime is worth it - and whether they are even allowed to decide that. And then everyone has to know: the caterer, who isn't in the group; the client, who wants it in writing; the 600 guests, who would just like to know where to park.

That is usually where the plan breaks. Not because people don't care, but because a revised plan sent into a group chat is not agreement. Nobody knows who has read it, who has agreed, and who is still working from version one. The debrief after a big event kept coming back to that moment: the caterer who still worked from the old timing, the client who first saw the extra cost on the invoice, the guests waiting at the wrong entrance.

We had planned to build something for this for a long time. There was always a next event. When this hackathon came up - WhatsApp, RCS, SMS and email as AWS services, with agentic AI on top: it was a perfect fit.

And while building it, it became clear that the problem isn't really about events. It shows up wherever several companies work on one plan and talk to each other on their phones.

What it does

Comsemble keeps every party in a multi-company operation on the same plan - and knows who isn't there yet.

One plan everyone works from. An organizer builds a versioned plan from a brief or a template: tasks, dependencies, milestones, who is responsible, and what each supplier charges. Every change creates a new version, and every version knows who has agreed to it.

Changes come in as messages. A supplier writes "The truck is delayed by 60 minutes" on WhatsApp, answers an SMS, or replies to an email. No app, no login, no form. Comsemble understands what changed and which part of the plan it touches.

Every option has a price. Deterministic code moves the timeline and prices the options from the suppliers' own rate rules: accept the delay and pay the overtime, or shorten something else and keep the milestones. Every cost line names the rule it came from and is labelled as an estimate.

The right person decides - where they already are. A policy says who decides what, and up to which amount. The decision request reaches that person on their channel; one tap on WhatsApp, a button on an RCS card or a signed link in an email commits the new version. The same decision on two channels at once commits exactly once.

"Sent" is not "agreed". After a decision, everyone affected gets the new version and is asked to confirm it. The project reads "awaiting confirmation" until the last one has, then "coordinated". Per person, per plan version. Provider acceptance, delivery and confirmation are three different facts, and Comsemble keeps them apart.

Everyone on the channel they have. WhatsApp for those who use it, an RCS card with "Add to calendar", "Show location" and "Call organizer" for those who don't, SMS as the fallback, and email for whoever needs it in writing - the client's change order shows only what the client should see.

A "no" is not lost. When a supplier refuses ("I cannot serve hot food after 19:15"), the project shows an exception and a recalculated option goes to the organizer. A refusal never turns into a silent "sent".

Everyone can take part - not just the core team. Every group - guests, crew, volunteers, suppliers - gets a join code, a QR code and a printable poster. Someone scans it, sends JOIN, and is in: no app, no account. Then they can ask what they would otherwise ask the person at the door. "Where can I park?" is answered from what the organizer wrote for that audience; "When do I start?" from that person's own slice of the plan. Anything without a source goes to a human, and the answer can be saved for the next one who asks.

It remembers. What a contact said is kept with its date and the message it came from, shown on the contact's page, and can be forgotten by the organizer. Memory never changes who decides.

AI suggests, code decides. Bedrock reads the messages, answers the questions and drafts plans. It never commits a plan, approves money, contacts a supplier or changes a permission. "I am the organizer" in a message changes nothing.

Works on its own - or behind your CRM. Comsemble can be the planning tool, or it can run headless: a CRM or field-service tool creates the job through the API, Comsemble gets the people to agree, and the CRM receives decisions and confirmations as signed webhooks.

Where it fits. Anything where several companies share one plan and a change costs money: events and conferences, trade fair builds, film and TV shoots, construction phases, field service with subcontractors, tours, relocations. The core stays the same; a project's type only changes its vocabulary - an "Event" with "Guests" becomes a "Job" with a "Customer address".

How I built it

Comsemble is a SvelteKit web app and a stateless worker on ECS Fargate, with RDS PostgreSQL for plans, decisions, confirmations and the audit trail. One CDK app deploys everything to eu-central-1.

The channels are three AWS communication services: AWS End User Messaging Social for WhatsApp, AWS End User Messaging for RCS and SMS, and Amazon SES for email in both directions. Their events and all internal jobs go through one SQS queue. Inbound email is only accepted after DMARC, spam and virus checks, and only from a verified sender.

Amazon Bedrock does the reading: Claude Haiku interprets incoming messages, Claude Sonnet drafts plans, a Bedrock Guardrail screens what comes in, and every model output is validated before the application touches it. AgentCore Memory is wired in for what contacts said, and Bedrock Knowledge Bases on S3 Vectors hold what the organizer wrote down for each audience.

Consent is built in. A number an organizer adds gets a code first and receives nothing else until it is confirmed. A JOIN is sender-initiated. And every outbound message goes through block lists before any provider call, so a test can never text a stranger.

Challenges

Implementing and coordinating channels takes days: WhatsApp templates wait for Meta's review. RCS in Germany needs a brand verification letter. SMS starts in a sandbox with a one-dollar spending limit. I ended up adding a Canadian number because it could be registered without a request. So I built everything against fake channels with the same contracts first, and kept the real steps for the end.

Judges in another time zone: The judges work in US time, the demo event happens in Germany. So the demo resets every night and the event always takes place that same day, during US working hours.

Untrusted text: Every message is written by someone who could be wrong, or lying. Authority comes from the plan and the policy, never from what a message claims.

Accomplishments that I'm proud of

After a long time of "we should build that", it now exists - live on app.comsemble.com, deployed from one CDK app.

A message on WhatsApp changes a versioned plan under deterministic rules, and Comsemble knows who still has to agree - per person and per plan version.

The AI has approved exactly zero euros. Not as a promise, but because nothing in the code lets it.

A refusal is a state with a new option, not a message nobody saw.

Anyone can join an operation by scanning a poster, without an app or an account.

What I learned

Sending a plan is not agreement. That one sentence turned into the whole product.

Knowing the customer for years saves weeks of guessing, where the customer helped me guide through decissions.

Getting a channel approved takes longer than building on it. Start the paperwork on day one.

A date in a test is a time bomb.

What's next for Comsemble

A first real event with MA-Events - with a measured manual baseline before I claim a single minute saved.

Approved WhatsApp templates and a launched RCS agent.

A second copy of the demo where you join with your own phone and get real messages.

The next kinds of work: field service, film shoots, construction phases.

There is a lot going on right now. The project is originally built for events but I tried to build it in a way so that it is generalized towards all kinds of business processes. The UI and UX definetly needs some work.

Try it yourself

Where: https://app.comsemble.com - the login is in the repo's README. All judges share one account and one demo workspace.

The demo. MA-Events GmbH produces the 25-year jubilee of Northlight GmbH: 600 guests in Lüneburg, Germany, with Marc Berendsen as producer - that is you when you sign in. MA-Events is a real agency; the event, the people, the phone numbers and every cost are made up and labelled [DEMO]. Costs are estimates from the suppliers' rate rules.

It resets every day. Every night at 03:00 New York time (midnight in California, 08:00 / 09:00 in Berlin), the demo starts over: plan version 1, nothing changed yet, and the event takes place that day. Doors open at 18:00 in Lüneburg - 13:00 ET / 10:00 PT until 31 October, 12:00 ET / 09:00 PT from 1 November. A banner on every page shows the next reset in your own time. What other judges do during the day stays visible until then.

Nothing real is sent. The demo project is simulated: every message goes to a built-in Simulator, not to a phone. You play every party yourself - the supplier, the client, the caterer - in a phone frame next to the app.

Next to it is a real copy, "Northlight 25-year jubilee [DEMO:PROD]": the same event on live channels, where messages go out over WhatsApp, RCS, SMS and email to real phones - and you can join it with your own phone by sending the join code shown on its overview. You will get real messages for that day's event; your data is deleted at the next reset.

Five minutes:

  1. Open "Northlight 25-year jubilee [DEMO]". The header reads coordinated, plan v1. Have a look at Plan › Graph.
  2. Messages › Simulator, recipient Mia (stage supplier). Send: The truck is delayed by 60 minutes in traffic. Watch for "Change understood" and "2 options calculated".
  3. Open the change. Option A accepts the shift for EUR 217.50 and breaks milestones; Option B shortens the soundcheck for EUR 67.50. Each cost line names its rule. The decision belongs to Sarah, the client.
  4. Simulator, recipient Sarah: tap B. Plan v2 is committed, and the header reads awaiting confirmation (0 of 1).
  5. Simulator, recipient Mia: tap Confirmed. The header reads coordinated.
  6. Simulator, recipient Jonas (caterer): ask Where do we unload? The answer comes from the project's knowledge, not from a guess.

The other path: choose A as Sarah instead, then decline the buffet change as Jonas. The project shows an exception and a recalculated option. The next reset brings everything back.

Built With

  • amazon-bedrock
  • amazon-bedrock-agentcore
  • amazon-cloudfront
  • amazon-ecs-fargate
  • amazon-rds-postgresql
  • amazon-ses
  • amazon-sqs
  • amazon-web-services
  • aws-cdk
  • aws-end-user-messaging
  • bedrock-knowledge-bases
  • claude
  • docker
  • drizzle-orm
  • eventbridge-scheduler
  • svelte-flow
  • sveltekit
  • tailwind-css
  • typescript
  • whatsapp-business-api
Share this project:

Updates

Submission history