Kickoff Funds — Project Story
Inspiration
German grassroots football lives off volunteers. The treasurer of an amateur club is usually someone with a day job who spends Sunday evenings on bookkeeping — and somewhere between training schedules and referee fees, funding deadlines quietly slip by. There are dozens of youth-development grants from the DFB, state sports federations, and foundations that clubs never apply for, not because they're ineligible, but because nobody has time to find them, check eligibility, and write yet another application. That felt like exactly the kind of skilled-but-tedious work AI agents should do — while a human keeps the final say.
What it does
Kickoff Funds is an agentic funding officer for grassroots football clubs. A club official logs in (AWS Cognito, fully multi-tenant — every club sees only its own data), maintains a structured club profile, and then three agents take over:
- The Discovery Agent retrieves and normalizes ~29 German youth-development grants from a curated corpus into a common schema.
- The Matching Agent scores every grant 0–100 against the club's real profile (legal form, member count, youth ratio, region, project needs) using Claude on Amazon Bedrock — with a human-readable rationale for every score. If eligibility data is ambiguous, it refuses to guess and flags the grant "Review Required" instead of fabricating a score.
- The Drafting Agent writes a tailored grant application grounded only in verified profile facts, inserting explicit
[MISSING: …]placeholders rather than inventing content.
Every step of every agent streams as a live reasoning trace into the dashboard over WebSocket, and nothing is ever submitted without explicit human approval in the Approval Inbox. A pipeline tracker watches deadlines and closes expired opportunities automatically.
How we built it
- Agents: Three Python agents with Strands-style tool decomposition (load_corpus, score_opportunity, compose_section, …), reasoning via Claude Haiku 4.5 on Amazon Bedrock through an EU cross-region inference profile.
- Backend: FastAPI on AWS Lambda (Mangum), API Gateway REST + WebSocket APIs, DynamoDB for profiles/opportunities/inbox/traces, S3 for the corpus and drafted applications, EventBridge for hourly deadline checks — all defined in AWS CDK.
- Frontend: Vue 3 + Pinia SPA with live WebSocket updates, collapsible reasoning traces, and direct Cognito authentication.
- Long-running agent runs are dispatched as asynchronous Lambda self-invocations so the API returns 202 instantly while traces stream to the browser.
- One-command deployment: a single script builds the Lambda bundle, deploys the CDK stacks, configures Cognito, seeds the corpus, deploys the frontend, and then runs 23 automated end-to-end checks against the live system.
Challenges we ran into
- API Gateway's 29-second limit vs. real agent work. Scoring 29 grants means 29 LLM calls. We redesigned the invocation model mid-hackathon: endpoints validate and return 202, then the Lambda invokes itself asynchronously to run the agents, streaming progress over WebSocket.
- Bedrock region reality. Our target region (eu-north-1) has no on-demand Claude — everything runs through inference profiles, and the account additionally needed Anthropic's use-case form submitted before any invocation would succeed. Debugging "ResourceNotFoundException" down to a compliance form was a journey.
- No Docker on the build machine, so CDK's container bundling was off the table. We built the Lambda package with a cross-platform pip install targeting the Lambda runtime instead.
- Death by details: DynamoDB rejecting Python floats (everything becomes
Decimal), Cognito custom claims namedcustom:club_idwhile the code expectedcustom:clubId, and middleware exceptions surfacing as 500s in Lambda but 401s in local tests. Cloud behavior is the only truth — which is why we made the deployment script validate the real deployed system, not just unit tests.
Accomplishments that we're proud of
- It's actually deployed and verified — not a localhost demo. The final deployment run passes 23 automated end-to-end checks: Cognito login, cross-tenant 403s, data retention, discovery, matching, drafting, S3 draft storage, inbox approval, live traces, WebSocket, frontend.
- Honest AI by design. The Matching Agent flagged the intentionally ambiguous grant in our corpus as "Review Required" with its uncertainty reasoning visible — a live failure-recovery moment instead of a hidden hallucination.
- Full transparency: 650+ reasoning-trace entries persisted and streamed, so an evaluator can watch every tool call the agents make.
- 233 passing tests, including property-based tests for tenant isolation, no-auto-submit guarantees, and draft grounding.
What we learned
Agentic systems fail at the seams, not in the prompts. The LLM parts worked almost immediately; the real engineering was the contract between agents and infrastructure — timeouts, auth claims, serialization, region-specific model access. We also learned that "validate against the deployed system" beats "the tests pass locally" every time: several bugs (mock-DB dev mode, middleware 500s, float serialization) were invisible until a script exercised the live stack end-to-end.
What's next for Kickoff Funds
- Implement reasoning traces — reasoning traces are not yet available. They will be added next.
- Live grant discovery — replace the seeded corpus with crawlers/APIs for federal, state, and foundation funding databases.
- Real submission flows — generate funder-specific PDFs and track submitted applications through decision.
- Deadline nudges via email/push so the deadline logic already running hourly reaches volunteers where they are.
- More clubs, more sports — the multi-tenant architecture already isolates every club; opening it up to handball, athletics, or any Verein is mostly a corpus problem.
- Learning from outcomes — feed back which applications won funding to sharpen the Matching Agent's scoring over time.
Built With
- amazon-web-services
- bedrock
- python
- s3
- vue
Log in or sign up for Devpost to join the conversation.