Inspiration

AI agents are getting the keys to real systems — refunds, databases, customer messages. They can now act, not just suggest. But "autonomous" shouldn't mean "unsupervised." The moment an agent can spend money or drop a production table, a human needs to be able to say "wait — not like that." I wanted a clean, reusable way to put a person in the loop exactly where teams already work: Slack.

What it does

Aegis is a human-approval control plane for AI agents. Before an agent performs a high-risk action, it calls Aegis over MCP and pauses. Aegis posts a rich Block Kit approval card to Slack where a human can:

  • Approve — the agent proceeds
  • Deny — the agent safely aborts
  • ✏️ Edit & Approve — change the agent's arguments first (e.g. lower a refund from $1,200 to $800); the agent then runs the corrected action and reports the change
  • Request Info

Around that core, Aegis adds:

  • Policy engine — auto-approve low-risk actions, require N-of-M approvals for critical ones (like dropping a production table), and auto-expire stale requests (TTL).
  • Plain-language summaries of every action via Amazon Bedrock, so approvers don't read raw JSON.
  • Related Slack context surfaced with the Real-Time Search API — the relevant conversation is pulled right onto the card.
  • Full audit log of every decision.

How I built it

  • An MCP server exposes request_approval, check_approval, and wait_for_approval, so any agent or framework can adopt the gate without changing its logic. In the demo, an Amazon Bedrock agent (Claude Sonnet 4.6) drives the loop via the Converse API and tool use.
  • A Slack app on Bolt (Socket Mode) renders the Block Kit cards and handles Approve / Deny / Edit & Approve, including a modal to edit the JSON arguments.
  • A policy engine evaluates risk and amount to decide auto-approve / N-of-M / single human, with a configurable TTL.
  • Context enrichment: Amazon Bedrock (Claude Haiku 4.5) writes the plain-language summary, and Slack's Real-Time Search (assistant.search.context) finds related messages and attaches them with permalinks.
  • Every request and decision is persisted to an audit log.

Built with: TypeScript · Slack Bolt (Socket Mode) · Model Context Protocol (MCP) · Amazon Bedrock · Slack Real-Time Search API.

Challenges I ran into

  • Action tokens for Real-Time Search. assistant.search.context needs a fresh action_token, which only arrives on a Slack assistant / mention event and lives for just minutes — yet approval requests originate outside any Slack event. I cache the latest token so out-of-band approval cards can still search, and refresh it with a quick @mention before a run.
  • Edit, not just gate. A plain yes/no felt too blunt — real reviewers want to correct an agent, not only stop it. Building Edit & Approve is the feature I'm most proud of.
  • Designing the policy engine so the obvious cases (a $45 goodwill refund) don't page a human, while the dangerous ones (dropping a prod table) demand two.

What I learned

  • A good approval is less about a button and more about context: the summary and the related conversation are what turn a rubber stamp into a real decision.
  • MCP is the right seam for this. Because the gate is fully decoupled from the agent, any agent can opt in, and the human-control surface lives natively in Slack.

What's next for Aegis

  • Policy-as-code with per-action approver routing
  • Approvals from inside Slack AI assistant threads
  • Drop-in connectors for popular agent frameworks, and a hosted version

Built With

  • amazon-bedrock
  • block-kit
  • claude
  • mcp
  • model-context-protocol
  • node.js
  • real-time-search-api
  • slack
  • slack-bolt
  • socket-mode
  • typescript
Share this project:

Updates