Inspiration
Okay A completely real answer... We saw a hackathon track, Agents for Good, and thought, okay, this fits what we can actually build in the time we have. But that's not the complete story... Every year, right around June, the news in this part of the world turns into the same rerun. Monsoon hits. Somewhere in Assam, or Himachal, or Kerala, a hillside gives way at three in the morning while people are asleep. Monsoon-linked disasters killed 3,238 people across India in 2024 alone, floods, landslides, lightning, buildings that just came down under saturated ground. Wayanad happened that July. A hillside tore apart above Mundakkai and Chooralmala, cut off whole villages, at least 123 people dead. Some of those villages weren't even reachable by road afterward. Choppers had to go in. Centre for Science and EnvironmentWikipedia You grow up in this part of the world, this stuff is background noise by the time you're ten. Every monsoon, somebody's village floods, somebody's hillside slides, somebody's family doesn't make it out. You stop flinching. That's the actual terrible part, not that it happens, but that it happens so often it just becomes weather. And what usually kills people in these events isn't the water or the mud itself, not really. It's that the warning existed somewhere and never reached the person who needed to move. It's that two rescue teams showed up to the same collapsed street not knowing the other one was already there. It's that some field worker flagged a weak slope three days earlier and that flag sat in a WhatsApp forward nobody escalated. So when the hackathon problem statement showed up, agent orchestration, hazard feeds, whatever the framing was, some part of my head that wasn't thinking about judging criteria went straight there. I didn't consciously sit down and think "this is for every monsoon I've read about since I was a kid." I picked a track that made engineering sense. But the shape of the problem, information that exists and just doesn't reach anyone in time, that's not a coincidence. That's what happens when you've watched this exact failure repeat every June for as long as you can remember. It rewires what "urgent" means to you without asking permission. Then me and my partner...
What it does
Beacon watches live hazard feeds, USGS for earthquakes, GDACS for global alerts, NWS for severe weather. When something crosses a severity threshold for a region your org cares about, it doesn't just ping you and stop there. It runs through six stages.
Triage checks if the event is even relevant and how urgent. Workspace Investigator uses Slack's Real-Time Search API to pull your org's own live context: which channels mentioned the region, what resources got flagged, who said they'd be around. External Intelligence hits five MCP servers for verified ground-truth data (magnitudes, weather severity, geospatial stuff). Evidence Synthesizer takes all that raw material and tags it by confidence: verified fact, supported inference, weak inference, contested. Nothing gets stated as certain unless the evidence actually backs it. Response Planner builds a task DAG, not a flat checklist, real dependencies (task B can't start till task A's done). Red-Team Critic tears into the plan before a human ever sees it.
What comes out is a situation brief in Slack with a "Sources and Visibility" footer showing where each fact came from, plus a response plan ready to run, before anyone even asked for one.
There's also a Mission Timeline updating live as each stage finishes, so a coordinator can watch the reasoning happen instead of staring at a spinner.
How we built it
Core is a LangGraph supervisor graph chaining the six agents, each one picks up the accumulated state from whatever ran before it. Backend's FastAPI plus Postgres (pgvector for semantic search, alembic for migrations). Five MCP servers expose 48 tools across hazard querying, geospatial reasoning, resource lookups. The Slack layer runs on the real assistant.search.context RTS endpoint, not the old search API, using the coordinator's own user token. So the agent literally cannot see more than the coordinator already can.
The evidence-typing system was the architectural decision that mattered most. Every piece of information entering the pipeline gets typed, and a claim only makes it into the response plan if the evidence actually clears the bar for that confidence level. The pipeline can't just invent a resource because it sounds plausible.
For demos we built a replay harness that runs real historical events (the 2019 M7.1 Ridgecrest quake, an NWS flash flood warning for Midland, Texas) through the exact same production path as live polling. Not a demo mode, not a fork of the logic, the identical normalizer functions. There's a test asserting exactly that.
Challenges we ran into
The RTS migration bit harder than expected. assistant.search.context has a totally different response shape from the old search.messages, different field names, cursor pagination instead of offset, different scopes required. At one point Beacon was claiming to use RTS while quietly still calling the legacy endpoint under the hood. That got caught and fixed first, because a false technical claim in something judges can inspect is worse than just not claiming the feature.
The six agents themselves were another real problem. They already existed in the codebase, but wired up as six separate, disconnected mission types, not an actual pipeline. Chaining them through LangGraph so state accumulates properly, then surfacing that as a live Mission Timeline in Slack, took longer than building any single agent did on its own.
One gap got caught pretty late: the prompt injection detection and PII redaction functions were written, tested, sitting right there, and never actually called from anywhere. Untrusted Slack content was going straight into the model. Fixed it with one sanitization choke point in the workspace investigator, the single place external content enters the pipeline.
Accomplishments that we're proud of
The Sources and Visibility footer. It's not hardcoded copy. It counts the actual retrieved results, checks channel types, reports how many came from private conversations (always zero, since DMs are excluded in the code itself, not by some policy doc). If a DM ever slipped through, that number would show it immediately.
The Mission Timeline showing real, progressive reasoning. Most agent demos are a spinner then a result. This one shows the pipeline actually working through it.
What we learned
Epistemic humility turns out to be an engineering problem, not a philosophy one. If you want a system that doesn't hallucinate, the constraint has to live in the data model, claim types, confidence levels, evidence provenance, not in a prompt that just says "be accurate." The claim system is what makes "zero hallucination" something you can check, not just something you hope for.
Also, consent and data minimization work better as product features than as compliance footnotes. The coordinator-scoped token and the Sources footer aren't privacy policy, they're UI. They tell the user exactly what the system read and didn't read. That's a cleaner story than "we follow best practices," because you can just point at the screen.
What's next for BeaconOS
Multi-org coordination through Slack Connect. A shared Connect channel during a joint response becomes a common situation brief and task DAG across org boundaries, while each coordinator still only sees what their own token allows.
Widening hazard coverage to WHO disease outbreak alerts and OCHA situation reports.
Longer term, making confidence thresholds configurable per org, so a small local nonprofit with barely any verification capacity can run this differently than a large INGO with a dedicated info management team.
Built With
- alembic
- docker
- fastapi
- gdacs
- geminiapi
- langgraph
- mypy
- nwsweatherapi
- opentelemetry
- pgvector
- postgresql
- pydantic
- pytest
- python
- ruff
- slackbolt
- slackmcp
- slackrealtimesearchapi
- structlog
- tenacity
- usgsearthquakeapi
Log in or sign up for Devpost to join the conversation.