Skip to content

About

agentic payment system

Topics

Resources

Stars

2 stars

Watchers

1 watching

Forks

Repository files navigation

Governed Payments Platform — Account (KYC) + Wallet + Transfer slice

A greenfield vertical slice of a governed payments platform: three domains — account (KYC), wallet, and transfer (P2P) — where an agent orchestrates through governed tools while deterministic services own their data and enforce the money-safety invariants transactionally. The account and wallet agents run on LangChain; the transfer agent runs on CrewAI — proving the governance path (kernel + policy + audit) is framework-agnostic.

Every model/tool action passes through an in-process governance kernel that returns one of four verdicts — allow | deny | escalate | transform — and records the decision to an append-only audit log.

browser → web-ui BFF → governed tool (kernel: policy + audit) → service API → PostgreSQL

Why this shape

  • Services own their data (Database-per-Service). account-service, wallet-service, and transfer-service each own a private PostgreSQL and are the only components that touch it. Others — including agents — reach data only through the service API.
  • The agent holds no database credentials. Its only capability is calling a service as a governed tool. The model never sees a connection string and cannot bypass a service invariant.
  • Safety-critical logic stays deterministic. balance >= 0, unique idempotency_key, one-wallet-per-user, and the KYC state machine are enforced in the service, in code — never left to the model. Policy is an advisory early-deny + audit layer on top.

Components

Component Path Role
agent_lifecycle_platform agent_lifecycle_platform/ Governance kernel, policy engine, audit + model wiring, governed-agent factory
account-service services/account/service/ Users + KYC system of record (FastAPI + Postgres)
wallet-service services/wallet/service/ Wallets + top-ups system of record (FastAPI + Postgres)
transfer-service services/transfer/service/ P2P transfers system of record (FastAPI + Postgres)
account-agent services/account/agent/ LangChain onboarding assistant (governed tools)
wallet-agent services/wallet/agent/ LangChain balance/top-up assistant (governed tools)
transfer-agent services/transfer/agent/ CrewAI P2P payment agent (governed tools)
audit-service audit_service/ Append-only JSONL audit sink + SSE stream
web-ui BFF web_ui/ Scenario console, approvals, live audit feed
model-service model_service/ Local open-weight model via Ollama (no API keys)

Governance model

Policies are declarative YAML (account, wallet, transfer). Each rule matches a condition (field / operator / value, or a compound all / any) against the tool-call context and prescribes a verdict. Highest-priority match wins; otherwise the defaults.action (fail-closed deny) applies.

The kernel (agent_lifecycle_platform/kernel.py):

  • wraps every tool so it is decided → audited → enforced on each call;
  • fails closed — an escalation with no approver resolves to deny;
  • refuses to start on an empty policy, so a mis-wired policy fails loudly instead of silently governing nothing;
  • populates governance context explicitly (e.g. the wallet KYC gate reads the user's KYC status into the decision context before create_wallet).

Design note: this slice ships a self-contained kernel that speaks the plan's full four-verdict policy language. The upstream declarative engine only supports allow/deny, and the upstream GovernancePolicy cannot express argument-conditional rules (caps, allow-lists), so a purpose-built kernel is the faithful realization of the plan's intent. Swapping in the upstream kernel later only touches agent_lifecycle_platform.

Run it

Requires Docker + Docker Compose.

# Full stack (services + Postgres x2 + audit + BFF + model + agents)
docker compose up -d

# Deterministic subset only (no LLM / model pull) — enough for the demo:
docker compose up -d account-db wallet-db account-service wallet-service audit-service web-ui

# Open the console
open http://localhost:8080

# Seed a few verified users
BASE=http://localhost:8080 scripts/seed.sh

# Run the golden scenarios headless (asserts every verdict)
BASE=http://localhost:8080 scripts/demo.sh

The LLM-driven agents (account-agent, wallet-agent) and model-service are included for the "agent narrative" path; the deterministic demo drives the BFF, which routes every action through the same governance kernel.

Agent route (LLM) — on by default

By default (AGENT_ROUTE=on) every console action is first sent to the local open-weight model (model-service, Ollama) so the LLM selects the governed tool to call — the request genuinely goes "through the agent". Governance then enforces the outcome, and the executed action is always the user's requested one, so a flaky small model can never corrupt the money flow; the model's choice is reported back (route: "agent", llm.chosen_tool, llm.matched) and shown in the console. If the model is unreachable the BFF falls back to the deterministic path automatically. Set AGENT_ROUTE=off (on the web-ui service) for the pure deterministic path used by the test suite. model-service pulls llama3.2:3b (~2 GB) on first start.

Using the console

The console at http://localhost:8080 is a three-step flow — 1 · Onboard → 2 · Log in → 3 · Wallet — with a live governance panel and audit feed on the right. Full walkthrough: docs/ui-console.md.

  • Onboard — create a user and submit KYC (must be verified to hold a wallet).
  • Log in — act as a verified user (no password auth in this slice; login selects the acting user).
  • Wallet — create a wallet, top up, and watch verdicts: $5,000 escalates (Approve/Reject), $12,000 and unlisted sources are denied, a repeated identical top-up is deduped by the service.

Cleanup

docker compose down -v   # also removes Postgres + audit + model volumes

Golden scenarios

# Action Verdict Enforced by
1 Onboard new user allow account policy
2 Submit KYC → verified allow account service state machine
3 Create wallet before KYC deny wallet policy (KYC gate) + service
4 Create wallet after KYC allow wallet policy
5 Top-up $50 from bank_ach allow wallet policy + service
6 Top-up from crypto_unknown deny wallet policy (source allow-list)
7 Top-up $5,000 escalate wallet policy + UI approval
8 Top-up $12,000 deny wallet policy (hard cap)
9 Duplicate top-up (same key) service dedupe (409) wallet service (unique constraint)
10 Read profile without purpose transform (masked) account policy
11 Out-of-scope tool (debit) deny wallet policy (least privilege)
12 Send $25 to a friend allow transfer policy + service
13 Send $600 escalate transfer policy + UI approval
14 Send $6,000 deny transfer policy (per-transfer hard cap)

Tests

python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest -q

Security posture

  • Fail-closed default deny; kernel refuses an empty policy (no silent fail-open).
  • Non-root containers; agents hold no DB credentials.
  • PII masked by default; full profile requires a declared data purpose.
  • Sensitive argument keys are redacted before audit.
  • Governance and service authorization are independent gates — either one denying stops the action.

About

agentic payment system

Topics

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages