Inspiration

Businesses don't lose money because nobody knows what's overdue. They lose it because chasing the money is a chore that happens after everything else — after the customer calls, after the invoices, after the day is already gone.

We wanted to find out whether a spoken request could drive the whole chase. Not "ask a chatbot about invoices," but "say what you want and have it done." So the test we set was deliberately narrow: someone says a sentence, and a payment workflow happens across multiple systems without them touching a UI. The person chasing money in a business is often not sitting at a desk, which is exactly when voice stops being a novelty and starts being the interface.

What it does

Ask "Do any customer have anything overdue?" and the assistant finds the customer, reads their invoices, works out what is late and by how long, and answers in one sentence: "Acme Corp has two overdue invoices totalling $3,200.00. The oldest is 18 days overdue."

Then say "send them a reminder and tell finance." It repeats back what it is about to do and who it reaches, waits for agreement, and only then emails the customer and posts to the finance channel — reporting what it did. Follow-ups work without repeating yourself, so "send them a reminder" resolves from the conversation.

How we built it

Three pieces, and the split is the point.

A self-hosted MCP server (mcp_server/) exposes five business-level tools over Streamable HTTP: resolve a customer, read what is overdue, summarise the account, send a reminder, notify finance. Every tool returns structured data and a sentence already phrased for speech, because the same result has to serve a dashboard and a voice assistant.

An agent loop (agent/) runs on Amazon Bedrock through the Converse API with toolConfig, behind a small interface with an OpenAI-compatible backend. It decides which tools to call and in what order.

A voice-first front end (web_demo/), because the Alexa+ add-on tooling is not available to hackathon participants. It is not a chat box with a microphone button: it has listening, thinking and speaking states: talking over it interrupts it mid-sentence, a misheard request is recoverable in one tap, and the wait time is on screen.

We also ship an Agent Skill (skills/cash-collection/). The track accepts an MCP server or an Agent Skill, so we built both. The server carries the capability; the skill carries the conduct — when to stop and ask, how to phrase an answer, what never to read aloud.

Challenges we ran into

The Alexa+ tools are gated with no application path. The track invites builders to see what Preview partners are building, while the FAQ puts the SDK, MCP Toolkit, CLI and Web Simulator behind select-partner access with no way for participants to apply. So we designed to the add-on contract instead of the add-on runtime, and wrote the constraint down in FRICTION_LOG.md rather than pretending otherwise.

An overdue invoice cannot be created on a fresh Stripe test account. Stripe rejects a due date in the past on create and on update. The supported route is a test clock — but clock objects are invisible to the account-wide list endpoints, and /v1/invoices has no test_clock filter while /v1/customers does. The seeder now builds the scenario on a test clock and the server scopes its reads to it, so anyone who clones the repository reproduces the demo data exactly.

The model leaked its own control tokens into a tool name. gpt-oss returned notify_finance_team<|channel|>commentary. Converse accepted that on the way out and rejected it on the way back in, so one bad name made every later request in that conversation fail validation. Names are now normalised the moment they arrive, before they reach the history or the server.

The assistant hesitated on every request. With one exact customer match, the tool returned a question — "I found Acme Corp. Is that the one?" — instead of the answer. Unit tests and the smoke test both passed while the experience was still wrong; only running it end to end surfaced it.

Accomplishments that we're proud of

The claims we can point at rather than assert:

  • the MCP session negotiates protocol 2025-11-25 and exposes five tools (python scripts/smoke_test.py);
  • a reminder was really sent through Stripe, and a message really arrived in Slack;
  • write actions refuse to run without confirmation, enforced in the tool rather than in the prompt;
  • 46 offline unit tests cover the business rules, the spoken phrasing and the model-output normalisation, with no network and no model involved;
  • the demo scenario is reproducible from an empty test account, which is what makes the video honest.

What we learned

Voice is a different product surface, not a different input device. Barge-in, recoverable mishearing, and one-sentence answers are not polish — without them the thing is unusable, and none of them show up in a chat UI's requirements.

And the tool layer is the right place to be strict. Prompt instructions are advisory; a tool that returns "this needs confirmation" is a guarantee. Everything we wanted to be true about safety ended up being easier to enforce one layer below the model.

What's next for Chaseline

With add-on runtime access, the work is the interface and nothing else — the MCP server, the tool contracts and the Agent Skill stay exactly as they are, because that is where the work is.

The obvious next steps are richer intents ("who should I chase first today?"), a scheduled daily briefing that surfaces newly overdue invoices without being asked, and a policy layer for who is allowed to authorise sending a customer a demand for money.

Built With

  • agent-skills
  • ai-agents
  • amazon-bedrock
  • amazon-web-services
  • apache-2.0
  • boto3
  • fastapi
  • fastmcp
  • function-calling
  • gpt-oss
  • llm
  • mcp-server
  • model-context-protocol
  • open-source
  • pydantic
  • python
  • requests
  • rest-api
  • slack
  • streamable-http
  • stripe
  • uvicorn
  • voice-assistant
  • web-speech-api
Share this project:

Updates

Submission history