AI-assisted financial workflow orchestration service for the Ancore account abstraction layer.
MVP — health, draft-intent, and intent validation routes are implemented. The service drafts intents only; it never executes transactions autonomously (requiresConfirmation is always enforced).
| Requirement | Value |
|---|---|
| Node.js | >= 20.0.0 |
| Package manager | pnpm >= 9.0.0 |
| Port | PORT env var (default: 3001) |
| Variable | Required | Default | Description |
|---|---|---|---|
PORT |
No | 3001 |
HTTP listen port |
NODE_ENV |
No | production |
Runtime environment (production / development) |
SERVICE_VERSION |
No | 0.1.0 |
Version string returned by the /health endpoint |
ANTHROPIC_API_KEY |
No | unset | Enables the Claude Haiku (claude-haiku-4-5) provider for /agent/draft-intent. When unset, unavailable, or when the LLM errors/times out/returns invalid output, the endpoint transparently falls back to a deterministic parser — the endpoint always succeeds. |
Health probe used by Docker HEALTHCHECK and load-balancer readiness checks. No authentication required.
Response 200:
{
"status": "ok",
"uptime": 42,
"timestamp": "2026-05-29T14:00:00.000Z",
"service": "ai-agent",
"version": "0.1.0"
}Drafts financial action intents from natural language prompts. Rate-limited to 60 requests/minute and maximum prompt length of 2000 characters.
Backed by Claude Haiku (claude-haiku-4-5, tool-forced structured output validated against the same Zod schemas as /v1/intents/validate) when ANTHROPIC_API_KEY is set, with an automatic, dependency-free deterministic fallback parser when the LLM is unavailable, errors, times out, or returns output that fails schema validation. The response's source field ("llm" or "deterministic") tells you which path produced the draft.
Every response is a draft only — status is always "draft" and requiresConfirmation is always true, enforced server-side by enforceNoAutonomousExecution() before the response is returned (a guardrail violation is a 500, never a silent pass-through). Nothing in this service ever signs or submits a transaction.
Request Body:
{
"prompt": "Send 10 XLM payment to Alice",
"accountId": "GA2C5RFPE6GCKMY3E5CCXBVOV2BLTCED63WBZ3XCABN35Y72EO6S2N3S"
}Example curl Command:
curl -X POST http://localhost:3001/agent/draft-intent \
-H "Content-Type: application/json" \
-d '{
"prompt": "Create an invoice for 10 XLM",
"accountId": "GA2C5RFPE6GCKMY3E5CCXBVOV2BLTCED63WBZ3XCABN35Y72EO6S2N3S"
}'Response 200 (Success):
{
"status": "draft",
"requiresConfirmation": true,
"summary": "Drafted invoice intent",
"intent": {
"type": "invoice",
"amount": "10",
"asset": "XLM",
"recipient": "GA2C5RFPE6GCKMY3E5CCXBVOV2BLTCED63WBZ3XCABN35Y72EO6S2N3S",
"dueDate": "2026-07-27T16:00:00.000Z"
},
"risk": {
"score": "low",
"flags": []
}
}Response 413 (Payload Too Large):
{
"error": "Prompt exceeds maximum length limit of 2000 characters"
}Response 429 (Rate Limited):
{
"error": "Too many draft-intent requests. Rate limit exceeded.",
"retryAfterSeconds": 45
}Validates agent-extracted intents against strict Zod schemas without executing transactions.
Supported Intents:
- Payment Intent (
payment): Transfer funds. Requiresamount,asset(XLMorUSDC), anddestination. - Invoice Intent (
invoice): Request invoice creation. Requiresamount,asset(XLMorUSDC),recipient(supports Unicode multilingual), anddueDate(valid parseable date).
Example curl Command:
curl -X POST http://localhost:3001/v1/intents/validate \
-H "Content-Type: application/json" \
-d '{
"type": "payment",
"amount": "250.00",
"asset": "USDC",
"destination": "GA2C5RFPE6GCKMY3E5CCXBVOV2BLTCED63WBZ3XCABN35Y72EO6S2N3S"
}'Response 200 (Valid):
{
"valid": true,
"intent": {
"type": "payment",
"amount": "250.00",
"asset": "USDC",
"destination": "GA2C5RFPE6GCKMY3E5CCXBVOV2BLTCED63WBZ3XCABN35Y72EO6S2N3S"
},
"requiresConfirmation": true,
"risk": {
"score": "medium",
"flags": ["high_value_transaction"]
}
}Response 400 (Invalid Schema):
{
"errors": {
"fieldErrors": {
"destination": ["Required"]
}
}
}docker build -t ancore/ai-agent:latest services/ai-agentdocker run -d \
--name ai-agent \
-p 3001:3001 \
-e NODE_ENV=production \
-e SERVICE_VERSION=0.1.0 \
ancore/ai-agent:latestcurl http://localhost:3001/healthdocker inspect --format='{{.State.Health.Status}}' ai-agent# Install dependencies (from repo root)
pnpm install
# Build
pnpm --filter @ancore/ai-agent build
# Run tests
pnpm --filter @ancore/ai-agent test
# Start (development, requires ts-node)
pnpm --filter @ancore/ai-agent devAll requests are logged as structured JSON objects to stdout by a request logger middleware.
To prevent PII and prompt leaks, the logging system automatically redacts sensitive fields like prompt and freeText from all log output, even when NODE_ENV is not production. If you run the service with debug logging enabled, the full request bodies will still never expose user prompts.
/agent/draft-intent additionally writes a draft_intent_audit log entry per request (timestamp, accountId, source, intentType, riskLevel, and a promptRedacted field). promptRedacted runs the prompt through redactSecrets() (src/logging/redact-secrets.ts), which replaces Stellar secret keys (S + 55 base32 chars), seed phrases (12+ consecutive lowercase words), and API-key-shaped tokens with [REDACTED] — see src/logging/__tests__/redact-secrets.test.ts for the exact patterns covered.
Example log entry:
{
"level": "info",
"timestamp": "2026-05-31T14:00:00.000Z",
"message": "request_complete",
"route": "/agent/draft-intent",
"method": "POST",
"statusCode": 200,
"durationMs": 42,
"accountId": "123",
"intentType": "payment"
}The Dockerfile uses a three-stage multi-stage build:
| Stage | Base image | Purpose |
|---|---|---|
build |
node:20-alpine |
Compile TypeScript → dist/ |
deps |
node:20-alpine |
Install production-only node_modules |
runtime |
node:20-alpine |
Minimal runtime; runs as non-root user |
Security properties of the runtime image:
- Runs as a non-root user (
ancore:ancore, created at build time) - Only production dependencies are present — no TypeScript compiler, no test tools
curlis installed solely for the HEALTHCHECK probe
- Natural-language to financial action intent parsing
- Safety checks and user confirmation flows
- Draft invoice / payment request generation
- Routing to off-chain analytics / risk systems before settlement