AgentBridge Africa
README.md
# AgentBridge Africa
Hardened multi-agent bridge for African payment rails: **native MCP safety annotations**, **`.well-known` server discovery**, **HTTP 402 budget hard-stops**, and **NIST OSCAL 1.2.1 audit packs**.
Local-context first (locale, rails, connectivity) — not a generic chatbot.
Inspired by: [africa-payments-mcp](https://github.com/kenyaclaw/africa-payments-mcp), [mpesa-mcp](https://github.com/gabrielmahia/mpesa-mcp), LangGraph budget control, Harbor/LangChain golden-trajectory evals, NIST OSCAL.
## Runtime shape
```
oauth/pkce → policy_gate → planner → worker → HITL → verifier → BudgetGuardian (402)
│ │
└─ MCP tools / resources └─ OSCAL AR + POA&M
```
| Piece | Role |
|-------|------|
| MCP Server Card | `.well-known/mcp.json` — indexable discovery, no client handshake required |
| Tool annotations | `readOnly` / `destructive` / `idempotent` (+ MCP `*Hint` aliases) |
| Resources | Read-only state, profiles, balances, OSCAL artifacts |
| `BudgetGuardian` | Hard stop + **HTTP 402** + partial OSCAL evidence |
| OAuth 2.1 PKCE | Remote MCP endpoints are not unauthenticated proxies |
| HITL gate | Every destructive tool requires verified OTP/PIN/OAuth confirmation |
| Circuit breaker | Per-provider open/half-open; fallback queue on outage |
| `AgentState` v2 | Versioned public API; new fields optional with defaults |
| OSCAL exporter | Assessment Results + POA&M under `.venturalitica/runs/{run_id}/` |
| Eval harness | Golden YAML trajectories + production-trace sampler |
## Layout
```
AgentBridge-Africa/
├── .well-known/mcp.json # MCP Server Card
├── agentbridge/
│ ├── core/
│ │ ├── orchestrator.py # planner / worker / verifier lifecycle
│ │ ├── graph.py # checkpointed payment lifecycle graph
│ │ ├── checkpointing.py # PostgresSaver / AsyncPostgresSaver
│ │ ├── rail_switch.py # currency/country/health provider router
│ │ ├── policy.py # allow / block / escalate
│ │ ├── budget_guardian.py # typed HTTP 402 cost hard-stop
│ │ ├── router.py # A2A routing
│ │ ├── oauth.py # OAuth 2.1 + PKCE
│ │ ├── hitl.py # destructive-tool interceptors
│ │ ├── circuit_breaker.py
│ │ ├── telemetry.py # OTEL-shaped traces
│ │ └── state.py # AgentState schema v2
│ ├── payments/ # live-ready async capability packs
│ │ ├── engine.py # production ContextProfile facade
│ │ ├── daraja.py # Safaricom OAuth, STK, status query
│ │ ├── paystack.py # initialize + verify transaction
│ │ ├── mtn_momo.py # request-to-pay + status query
│ │ ├── runtime.py # secrets, egress allowlist, transport
│ │ └── registry.py # allowlisted dependency injection
│ ├── tools/
│ │ ├── payment_mcp.py # unified annotated MCP contracts
│ │ ├── payment_engine.py # provider-neutral payment facade
│ │ ├── payment_adapter.py # sandbox provider implementation
│ │ └── resources.py # read-only resources
│ ├── webhooks/
│ │ ├── security.py # HMAC/token/SPIFFE verification
│ │ └── handlers.py # dedupe + reconcile, never callback-final
│ └── compliance/
│ ├── oscal_exporter.py
│ └── schemas/ # OSCAL JSON v1.2.1 subset
├── agentbridge/migrations/ # ledger + atomic callback/outbox SQL
├── src/bridge/ # deprecated compatibility imports only
├── tools/ # deprecated compatibility imports/stub
├── evals/ # golden + production sampler
├── frontend/ # Next.js operator console
└── tests/test_budget_guardian.py
```
## Operator console
The responsive Next.js console in [`frontend/`](frontend/) demonstrates the production operator workflow: payment lifecycle visibility, provider health, run-cost budgets, reconciliation, immutable audit evidence, and five-step HITL approval. Demonstration identifiers are scrubbed; verifier references are accepted instead of raw OTPs, PINs, credentials, or recipient PII.
```bash
cd frontend
npm install
npm run dev # http://localhost:3000
# Production validation
npm run lint
npm run build
```
Dashboard data is typed mock data for now. Approval actions update local UI state only; they do not invoke a payment connector.
## Quick start
```bash
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
make eval
python -m pytest -q
# Live connector transport (credentials are still deployment-owned):
pip install '.[connectors]'
```
Discovery card (no live connection required):
```bash
cat .well-known/mcp.json
```
## MCP safety annotations
Tools **act**. Resources **read**. Orchestrators gate on flags:
```python
from agentbridge.tools import MPESA_STK_PUSH, MPESA_QUERY_STATUS
MPESA_STK_PUSH.annotations
# readOnly=False destructive=True idempotent=False
MPESA_QUERY_STATUS.annotations
# readOnly=True destructive=False idempotent=True
```
Destructive tools require `idempotency_key`, `payments:execute` scope, and verifier-backed OTP/PIN/OAuth confirmation. Every destructive call pauses in `awaiting_hitl`; amounts above `hitl_amount_threshold` receive enhanced review.
## Budget → HTTP 402
When `spent_usd > max_run_cost_usd` the guardian:
1. Sets `status=budget_exceeded` and `http_status=402`
2. Halts further tool invocations
3. Writes partial OSCAL evidence to `.venturalitica/runs/{run_id}/`
## OSCAL continuous compliance
```python
from agentbridge.compliance import Finding, export_oscal_results
export_oscal_results(run_id, findings)
# → assessment-results.oscal.json
# → poam.oscal.json (only when a control is not-satisfied)
```
Failed budget, AML, or payment-limit controls auto-generate a Plan of Action and Milestones linking each finding to a remediation task.
## Metrics (from `make eval`)
| Metric | Meaning |
|--------|---------|
| `n` | Trajectory count (happy + failure injection) |
| `success_rate_pct` | Golden trajectories matching expected outcome |
| `p50_latency_ms` | Median summed step latency |
| `median_cost_usd` | Median spend under BudgetGuardian |
Latest sandbox run: **7 / 7 expected outcomes (100%)**.
## Profiles
| File | Locale | Currency | Rails | Connectivity |
|------|--------|----------|-------|--------------|
| `profiles/en-NG.json` | en-NG | NGN | bank, ussd, mobile_money, paystack | intermittent |
| `profiles/en-KE.json` | en-KE | KES | mpesa, mobile_money, bank | intermittent |
| `profiles/offline-NG.json` | en-NG | NGN | ussd | **offline_first** (fail closed) |
## Safety
- `execute` requires `idempotency_key`
- Tool envelopes expose `readOnly` / `destructive` / `idempotent`
- Budget is a **hard stop** (HTTP 402), not a soft warning
- `offline_first` blocks remote and side-effect tools before the worker runs
- No infinite retry on tool timeout; circuit breakers open after repeated provider faults
- OAuth 2.1 + PKCE on remote MCP; tokens bound to exact scopes
- OpenTelemetry-shaped traces on every LLM / tool / policy span
See [`DEVELOPMENT.md`](DEVELOPMENT.md), [`docs/architecture.md`](docs/architecture.md), [`docs/production-architecture.md`](docs/production-architecture.md), [`docs/webhooks.md`](docs/webhooks.md), the [`Production Activation Verification audit`](docs/audits/production-activation-verification.md), the [`Context Router & PostgreSQL FSM audit`](docs/audits/context-router-postgres-fsm-audit.md), the [`Provider Connector audit`](docs/audits/provider-connectors-audit.md), [`docs/playbook.md`](docs/playbook.md), [`docs/mcp-safety.md`](docs/mcp-safety.md), and [`docs/oscal.md`](docs/oscal.md).
Default execution remains sandboxed. Live connector classes perform no network I/O until explicitly registered with deployment-owned secrets, policy, callback hosts, and egress configuration.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues