Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

cura-reach

A Human API for AI agents. Governed ask / notify / approve / schedule verbs over consented channels, with a failover ladder, scoped revocable tokens, per-touch budgets, and an audit trail for every attempt.

See SPEC.md for the full design (verbs, consent model, blessed tokens, the abuse-resistance model, and the premises this v1 rests on).

Why

Agents that reach real people keep reinventing the same five things badly: an unconsented channel, a rate limit nobody enforces, an audit trail that's just application logs, a credential that's either all-powerful or nonexistent, and a silent failure when the first channel doesn't work. cura-reach is the layer in between: one verb set, one policy layer, one audit shape, regardless of which channel actually carries the message.

Quickstart

pip install -e .

# Grant consent for a channel (opaque address reference, not stored in code):
python3 -m cura_reach.cli grant-consent --human alice --channel email --address alice@example.com
python3 -m cura_reach.cli grant-consent --human alice --channel task_queue --address queue:alice --priority 1

# Mint a scoped, revocable token for one agent, reaching only this human:
python3 -m cura_reach.cli mint-token --principal my-agent --scopes ask,notify --humans alice
# -> {"token_id": "tok_...", "secret": "..."}   (shown once; store it yourself)

# Ask. Email adapter falls back to the task-queue channel if unconfigured:
python3 -m cura_reach.cli ask --token-id tok_... --secret ... --human alice --question "Ship it?"

Or drive it from Python directly:

from cura_reach.bootstrap import build_engine
from cura_reach.models import ChannelType, Verb

engine, consent, tokens = build_engine()
consent.register_human("alice")
consent.grant("alice", ChannelType.EMAIL, "alice@example.com", source="onboarding")

token, secret = tokens.mint("my-agent", [Verb.ASK], ["alice"], budget_ref="budget:my-agent")
request = engine.ask(token.token_id, secret, "alice", "Ship it, or one more pass?")
print(request.status, request.channel_attempts)

The E2E demo

python3 demo/e2e_demo.py

Runs the full loop end to end with zero live network calls: mints a token, grants consent on two channels, asks a consenting test human, watches the email adapter fail over (unconfigured in a fresh checkout) to the task-queue adapter (delivers via a local JSONL outbox), then resolves the request and prints the full audit trail plus the budget draw it recorded. The same flow is asserted in tests/test_e2e.py.

What's implemented (v1 kernel)

  • Asks API: all four verbs (cura_reach/engine.py), backed by SQLite (cura_reach/storage.py), zero external dependencies.
  • Consent registry: per-human, per-channel, append-only consent ledger (cura_reach/registry.py::ConsentRegistry).
  • Blessed tokens: scoped, revocable, no-enumeration, budget-backed (cura_reach/registry.py::TokenRegistry).
  • Failover ladder: email -> task queue -> LinkedIn/Slack/SMS stubs (cura_reach/engine.py::Engine._walk_ladder, cura_reach/adapters/).
  • Audit: Action-shaped, append-only, idempotent-on-write (cura_reach/audit.py).
  • Budgets: shared daily draw ceilings, fail-loud on exhaustion (cura_reach/registry.py::BudgetLedger).
  • A2A/MCP surface (v0): a stdio MCP server exposing the four verbs as tools (cura_reach/mcp_server.py).

See SPEC.md section 11 for what's explicitly out of scope for v1, and section 12 for the premises this design rests on.

Configuration

All configuration is environment-variable driven and generic (no vendor or deployment names baked in):

Variable Purpose Default
CURA_REACH_SMTP_HOST / _PORT / _USERNAME / _PASSWORD / _FROM_ADDRESS / _USE_TLS Email adapter (own-mailbox send) unset (adapter reports unavailable)
CURA_REACH_QUEUE_URL / _TOKEN Task-queue adapter (HTTP POST) unset (falls back to a local outbox file)
CURA_REACH_QUEUE_OUTBOX Local outbox path when no queue URL is set .cura-reach/queue-outbox.jsonl
CURA_REACH_DB SQLite path for the CLI/MCP server .cura-reach/store.db
CURA_REACH_MCP_TOKEN_ID / _MCP_TOKEN_SECRET The token an MCP session authenticates as required for cura_reach.mcp_server

Tests

pip install -e ".[dev]"
pytest

License

Apache 2.0 (see LICENSE), matching the operator's other public infrastructure repos.

About

A Human API for AI agents: governed ask/notify/approve/schedule verbs over consented channels.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages