Sahaayak AI documentation
Setup, architecture and reference for Sahaayak AI, the AI back-office for Indian businesses. The public demo workspace uses seeded sample data, so don't upload confidential data there.
Questions about your deployment? Email [email protected].
Quickstart
Runs fully local with zero AWS. Flip USE_AWS=1 for the real cloud path.
cd backend && pip install -r requirements.txt uvicorn app.main:app --reload --port 8000 cd frontend && npm install && npm run dev # → http://localhost:5173 cd backend && pytest tests -v # 51 green python simulation/simulate_demo.py # 18/18 — the demo as a test USE_AWS=1 python simulation/check_aws.py # verify AWS handoff: 5/5
Demo tenant: ramesh_auto — Ramesh Auto Components, Faridabad.
Architecture
Browser ──▶ FastAPI ──▶ Sahaayak (orchestrator, Nova Pro) │ │ ├─ Vasool → invoices tools │ │ ├─ Sourcer → supplier tools │ │ ├─ Khata → cashflow tools │ │ └─ Nirmata → factory (previews + hires agents) │ │ │ ├─ Store ── USE_AWS=0: LocalStore (JSON) │ │ USE_AWS=1: DynamoStore (11 tables) │ ├─ Notifier ── ConsoleNotifier → SESNotifier (SES) │ ├─ Sessions ── FileSessionManager → S3SessionManager │ └─ Models ── MockModel (deterministic) → Bedrock Nova
One env var swaps every seam. Local mode is the dev/test path — the product is the AWS path. The contract between frontend and backend is frontend/mocks/contract.json.
Agents
@sahayakRoutes every message to the right specialist — or to Nirmata.
@vasoolOverdue invoices, aging report, payment reminders (draft-only).
@sourcerSupplier search, price compare, trust scores, MOQ pooling.
@khataReceivables vs payables timeline, 90-day-terms gap analysis.
@nirmataInterviews the owner → previews a spec → hires on confirmation. Generated agents get tool allowlists + draft-only guardrails.
API reference
Rendered live from contract.json — the single source of truth.
POST/auth/login
{
"provider": "google|phone|guest",
"provider_id": "[email protected]",
"name": "Ramesh Gupta",
"business": "Ramesh Hardware & Electricals"
}{
"token": "<signed HMAC token>",
"role": "owner",
"base_role": "owner",
"tenant_id": "ramesh_auto",
"user": {
"name": "Ramesh Gupta",
"business": "Ramesh Hardware & Electricals",
"city": "Faridabad",
"line": "hardware"
},
"onboarded": true
}GET/auth/me
{
"tenant_id": "ramesh_auto",
"role": "owner",
"base_role": "owner",
"perms": [
"*"
],
"exp": 1790000000
}POST/auth/role
{
"role": "viewer"
}{
"token": "<signed>",
"role": "viewer",
"base_role": "owner"
}POST/auth/invite
{
"role": "manager"
}{
"token": "<signed>",
"role": "manager",
"tenant_id": "ramesh_auto",
"expires_in_days": 30
}GET/dashboard/summary
{
"receivables": {
"total": 623900,
"overdue_count": 4,
"overdue_total": 190400,
"due_soon_total": 180500
},
"capital_locked_long_terms": 88700,
"payables_due_30d": 94400,
"pending_approvals": 2,
"agents": {
"total": 4,
"ai_hired": 1
},
"alerts_unread": 3,
"recent_activity": [
{
"ts": "2026-09-19T02:10:00Z",
"kind": "agent_created",
"text": "Nirmata hired 'Logistics Agent' for you"
},
{
"ts": "2026-09-19T01:44:00Z",
"kind": "reminder_sent",
"text": "Reminder sent to Sharma Motors (INV-0031)"
},
{
"ts": "2026-09-18T22:30:00Z",
"kind": "invoice_parsed",
"text": "Invoice INV-0045 parsed from photo → ledger"
}
]
}POST/chat
{
"tenant_id": "ramesh_auto",
"text": "Show my overdue invoices",
"agent_id": null,
"chat_id": "chat-4f2a9c1d3e",
"attachments": null
}{
"reply": "You have 4 overdue invoices totalling ₹1,90,400...",
"agent_name": "vasool",
"agent_tagline": "पैसा वसूलने वाला",
"actions": [
{
"type": "invoices_listed",
"data": {}
}
],
"trace": [
"sahayak",
"vasool"
],
"usage": {
"tools": [
"vasool"
],
"input_tokens": 0,
"output_tokens": 0,
"total_tokens": 0,
"cost_usd": 0,
"latency_ms": 12
},
"chat_id": "chat-4f2a9c1d3e"
}GET/chats
[
{
"id": "chat-4f2a9c1d3e",
"title": "Show my overdue invoices",
"agent_id": null,
"created_at": "2026-09-19T02:00:00Z",
"updated_at": "2026-09-19T02:05:00Z",
"message_count": 6,
"preview": "You have 4 overdue invoices totalling ₹1,90,400..."
}
]POST/chats
{
"tenant_id": "ramesh_auto",
"agent_id": null,
"title": ""
}{
"id": "chat-4f2a9c1d3e",
"agent_id": null,
"title": "Conversation",
"created_at": "2026-09-19T02:00:00Z",
"updated_at": "2026-09-19T02:00:00Z",
"messages": []
}GET/chats/{id}
{
"id": "chat-4f2a9c1d3e",
"agent_id": null,
"title": "Show my overdue invoices",
"created_at": "2026-09-19T02:00:00Z",
"updated_at": "2026-09-19T02:05:00Z",
"messages": [
{
"role": "user",
"text": "Show my overdue invoices",
"ts": "2026-09-19T02:00:00Z"
},
{
"role": "agent",
"agent": "vasool",
"tagline": "पैसा वसूलने वाला",
"text": "You have 4 overdue...",
"trace": [
"sahayak",
"vasool"
],
"actions": [],
"usage": {},
"mode": "chat",
"ts": "2026-09-19T02:00:05Z"
}
]
}PATCH/chats/{id}
{
"tenant_id": "ramesh_auto",
"title": "Overdue chase",
"agent_id": "vasool"
}{
"id": "chat-4f2a9c1d3e",
"title": "Overdue chase",
"agent_id": "vasool"
}DELETE/chats/{id}
{
"status": "deleted",
"id": "chat-4f2a9c1d3e"
}POST/chats/{id}/messages
{
"tenant_id": "ramesh_auto",
"messages": [
{
"role": "agent",
"agent": "system",
"text": "Scanned bill.jpg → INV-101"
}
]
}{
"id": "chat-4f2a9c1d3e",
"title": "Show my overdue invoices",
"agent_id": null,
"created_at": "2026-09-19T02:00:00Z",
"updated_at": "2026-09-19T02:05:00Z",
"message_count": 7,
"preview": "Scanned bill.jpg → INV-101"
}GET/agents
[
{
"id": "vasool",
"name": "Vasool",
"hindi_tagline": "पैसा वसूलने वाला",
"description": "Tracks invoices and chases payments",
"tools": [
"list_overdue",
"aging_report",
"draft_reminder"
],
"status": "active",
"created_by": "builtin",
"icon": "receipt",
"stats": {
"runs": 14,
"last_active": "2026-09-19T02:00:00Z"
}
}
]GET/agents/{id}
{
"id": "agent-l7x2",
"name": "Logistics Agent",
"hindi_tagline": "सामान पहुँचाने वाला",
"goal": "Find backup transport and book pickups when scheduled carriers fail",
"persona_prompt": "...",
"tools": [
"list_carriers",
"quote_pickup",
"book_pickup"
],
"created_by": "factory",
"status": "active",
"created_at": "2026-09-19T02:10:00Z",
"stats": {
"runs": 3,
"actions_taken": 1,
"last_active": "2026-09-19T02:15:00Z"
}
}GET/agents/{id}/context
{
"invoice_summary": {
"total_outstanding": 623900,
"overdue_total": 190400,
"oldest_overdue_days": 111
},
"capital_locked_90d": 88700,
"top_defaulters": [
{
"buyer": "Om Sai Traders",
"amount": 28700,
"days": 111
}
],
"recent_invoices": []
}POST/agents/preview
{
"name": "Logistics Agent",
"goal": "Find backup transport when pickups fail",
"tools": [
"list_carriers",
"quote_pickup",
"book_pickup"
]
}{
"valid": true,
"spec": {},
"warnings": []
}POST/agents
{
"tenant_id": "ramesh_auto",
"name": "Logistics Agent",
"goal": "...",
"tools": [
"list_carriers"
]
}{
"id": "agent-abc123",
"status": "active",
"created_by": "factory"
}GET/tasks
[
{
"id": "task-1",
"title": "Chase all invoices >30 days",
"agent_id": "vasool",
"status": "done",
"due": "2026-09-20",
"result": "Drafted 3 reminders",
"created_at": "2026-09-19T01:00:00Z"
}
]POST/tasks
{
"tenant_id": "ramesh_auto",
"title": "Get steel quotes under ₹65",
"agent_id": "sourcer",
"due": "2026-09-21",
"details": "raw steel coils"
}{
"id": "task-9",
"status": "todo"
}POST/tasks/{id}/run
{
"task_id": "task-9",
"status": "done",
"agent_name": "sourcer",
"result": "Balaji Steel at ₹62/unit...",
"actions": []
}PATCH/tasks/{id}
{
"col": "done",
"status": "done"
}{
"id": "task-9",
"status": "done"
}GET/calendar/events?from=&to=
[
{
"id": "ev-1",
"date": "2026-09-24",
"title": "INV-0041 due (₹56,000 — Khanna Industries)",
"kind": "invoice_due",
"ref_id": "inv-007"
},
{
"id": "ev-2",
"date": "2026-09-26",
"title": "Reminder fires: INV-0035",
"kind": "alert",
"ref_id": "alert-1"
},
{
"id": "ev-3",
"date": "2026-09-21",
"title": "Task: Get steel quotes",
"kind": "task",
"ref_id": "task-9"
}
]GET/notifications
[
{
"id": "n-1",
"kind": "action_required",
"title": "Reminder ready to send: INV-0031",
"body": "Namaste Sharma ji...",
"ref_id": "alert-x",
"created_at": "2026-09-19T02:00:00Z",
"status": "unread"
},
{
"id": "n-2",
"kind": "info",
"title": "Logistics Agent hired",
"body": "Nirmata created it after your transporter issue",
"created_at": "2026-09-19T02:10:00Z",
"status": "unread"
},
{
"id": "n-3",
"kind": "warning",
"title": "₹58,000 cash gap next week",
"body": "Payables due before receivables arrive",
"created_at": "2026-09-18T06:00:00Z",
"status": "read"
}
]POST/notifications/{id}/read
{
"id": "n-1",
"status": "read"
}GET/connectors
[
{
"id": "google_calendar",
"name": "Google Calendar",
"icon": "calendar",
"status": "available",
"description": "Push invoice dues + reminders to your calendar",
"items_synced": 0
},
{
"id": "airtable",
"name": "Airtable",
"icon": "table",
"status": "connected",
"connected_at": "2026-09-18T10:00:00Z",
"last_sync": "2026-09-19T01:00:00Z",
"items_synced": 32,
"description": "Sync ledger + suppliers to your base"
},
{
"id": "whatsapp",
"name": "WhatsApp",
"icon": "message",
"status": "available",
"description": "Send payment reminders via wa.me deep links"
},
{
"id": "tally",
"name": "Tally",
"icon": "ledger",
"status": "available",
"description": "Import existing invoices"
},
{
"id": "razorpay",
"name": "Razorpay",
"icon": "rupee",
"status": "available",
"description": "Payment links in reminders"
}
]POST/connectors/{id}/connect
{
"tenant_id": "ramesh_auto"
}{
"id": "google_calendar",
"status": "connected",
"connected_at": "2026-09-19T03:00:00Z"
}POST/connectors/{id}/disconnect
{
"id": "airtable",
"status": "available"
}GET/connectors/{id}/sync
{
"id": "airtable",
"last_sync": "2026-09-19T01:00:00Z",
"items_synced": 32,
"state": "ok"
}GET/channels
[
{
"type": "telegram",
"name": "Telegram",
"status": "connected",
"active": true,
"running": true,
"mode": "polling",
"identity": "sahayak_bot",
"agent_id": null,
"approved_users": [],
"pending_pairings": [],
"stats": {
"messages_in": 4,
"messages_out": 4
}
},
{
"type": "whatsapp",
"name": "WhatsApp Business",
"status": "available",
"active": false,
"running": false,
"mode": null,
"identity": null,
"agent_id": null,
"approved_users": [],
"pending_pairings": [],
"stats": {}
}
]POST/channels/{type}/connect
{
"tenant_id": "ramesh_auto",
"bot_token": "123:abc",
"agent_id": null,
"webhook_url": null,
"phone_number_id": "",
"access_token": "",
"app_secret": "",
"verify_token": ""
}{
"success": true,
"bot_username": "sahayak_bot",
"mode": "polling"
}POST/channels/{type}/disconnect
{
"success": true,
"status": "available"
}GET/channels/{type}/status
{
"type": "telegram",
"status": "connected",
"active": true,
"running": true,
"mode": "polling",
"identity": "sahayak_bot",
"approved_users": [
{
"chat_id": "123",
"name": "Ramesh",
"approved_at": "..."
}
],
"pending_pairings": [],
"stats": {},
"connected_at": "..."
}GET/channels/{type}/pending-users
{
"users": [
{
"chat_id": "123456",
"name": "Suresh",
"code": "482910",
"ts": "..."
}
]
}GET/channels/{type}/approved-users
{
"users": [
{
"chat_id": "123456",
"name": "Suresh",
"approved_at": "..."
}
]
}POST/channels/{type}/approve-user
{
"tenant_id": "ramesh_auto",
"chat_id": "123456"
}{
"success": true,
"user": {
"chat_id": "123456",
"name": "Suresh",
"code": "482910"
}
}POST/channels/{type}/deny-user
{
"tenant_id": "ramesh_auto",
"chat_id": "123456"
}{
"success": true
}POST/channels/{type}/revoke-user
{
"tenant_id": "ramesh_auto",
"chat_id": "123456"
}{
"success": true
}GET|POST /webhooks/{type}/{tenant_id} [EXISTS]
GET/settings
{
"business": {
"name": "Ramesh Auto Components",
"owner": "Ramesh Gupta",
"city": "Faridabad",
"line": "auto components"
},
"onboarded": true,
"prefs": {
"reminder_cadence_days": 7,
"auto_draft_reminders": true,
"approval_mode": "manual",
"language": "hinglish",
"notify_email": "[email protected]",
"disabled_tools": []
},
"mcp_servers": [
{
"id": "mcp-1",
"name": "Tally MCP",
"url": "http://localhost:9100/mcp",
"status": "configured"
}
]
}PATCH/settings
{
"prefs": {
"reminder_cadence_days": 5
}
}{
"status": "saved"
}POST/upload
multipart/form-data: file=<image|pdf>, tenant_id
{
"file_id": "f-001",
"filename": "invoice_0042.jpg",
"parsed": {
"invoice_no": "INV-0042",
"buyer": "Sharma Motors",
"amount": 45200,
"gst": 8136,
"due_date": "2026-10-05",
"items": "Brake pads x200",
"confidence": 0.93
},
"low_confidence_fields": []
}GET/invoices?tenant_id=&status=
[
{
"id": "inv-001",
"invoice_no": "INV-0038",
"buyer": "Sharma Motors",
"amount": 45200,
"due_date": "2026-09-10",
"status": "overdue",
"days_overdue": 9
}
]POST/invoices/{id}/reminder
{
"draft_id": "draft-1",
"status": "draft",
"body": "Namaste Sharma ji...",
"requires_approval": true
}POST/alerts/{id}/approve
{
"id": "alert-1",
"status": "sent",
"via": "console|ses"
}GET/suppliers?tenant_id=&q=
[
{
"id": "sup-1",
"name": "Balaji Steel",
"category": "raw steel",
"trust_score": 4.2,
"moq": 500,
"price_per_unit": 62,
"stock": "in_stock",
"lead_days": 4
}
]GET/carriers?tenant_id=&to=
[
{
"id": "car-1",
"name": "VRL Logistics",
"route": "Faridabad→Ludhiana",
"rate_per_kg": 4.5,
"next_slot": "tomorrow 7am",
"reliability": 4.6
}
]GET/alerts?tenant_id=&status=
[
{
"id": "alert-1",
"kind": "reminder",
"title": "INV-0038 due in 3 days",
"status": "pending_approval",
"fires_at": "2026-09-19T06:00:00Z",
"body": "..."
}
]GET/cashflow?tenant_id=
{
"receivables": [
{
"buyer": "Sharma Motors",
"amount": 45200,
"expected": "2026-10-05"
}
],
"payables": [
{
"vendor": "Balaji Steel",
"amount": 31000,
"due": "2026-09-25"
}
],
"gaps": [
{
"period": "Oct wk1",
"shortfall": 58000,
"reason": "90-day buyer terms vs 30-day supplier terms"
}
]
}POST/import/excel
multipart/form-data: file=<.xlsx>, tenant_id
{
"file_id": "f-imp-1",
"filename": "ledger.xlsx",
"collection": "invoices",
"imported": 34,
"skipped": 2,
"sample": [
{
"invoice_no": "INV-0101",
"buyer": "Kapil Auto",
"amount": 12400,
"due_date": "2026-10-02"
}
]
}GET/memories?tenant_id=
[
{
"id": "mem-1",
"text": "Sharma Traders always pays around 45 days — don't push hard",
"source": "owner",
"created_at": "2026-09-19T03:00:00Z"
}
]POST/memories
{
"tenant_id": "ramesh_auto",
"text": "Big orders go through GST invoice only",
"source": "owner|onboarding"
}{
"id": "mem-2",
"status": "saved"
}DELETE/memories/{id}
{
"status": "deleted"
}GET/search?q=&tenant_id=
{
"q": "sharma",
"results": {
"invoices": [
{
"id": "inv-001",
"title": "INV-0038 — Sharma Motors",
"meta": "₹45,200 · overdue 9d",
"ref": "#/app"
}
],
"suppliers": [
{
"id": "sup-1",
"title": "Balaji Steel",
"meta": "raw steel · trust 4.2",
"ref": "#/app"
}
],
"carriers": [],
"agents": [],
"tasks": [],
"memories": [],
"documents": [
{
"id": "f-001",
"title": "invoice_0042.jpg",
"meta": "uploaded 18 Sep",
"ref": "#/app"
}
]
}
}GET/artifacts?tenant_id=
[
{
"id": "art-1",
"title": "Tracking — ORD-1042",
"template": "tracking_page",
"visibility": "public",
"created_by": "agent-l7x2",
"created_at": "2026-09-19T03:00:00Z",
"share_path": "/a/art-1"
}
]GET/artifacts/{id}
{
"id": "art-1",
"title": "Tracking — ORD-1042",
"template": "tracking_page",
"visibility": "public",
"data": {
"order_id": "ORD-1042",
"carrier": "SafeRoad Carriers",
"from": "Ludhiana",
"to": "Faridabad",
"eta": "tomorrow 11am",
"status": "in_transit",
"progress_pct": 62
},
"created_by": "agent-l7x2",
"created_at": "2026-09-19T03:00:00Z",
"share_path": "/a/art-1"
}GET/public/artifacts/{id}
"same as GET /artifacts/{id}"PATCH/artifacts/{id}
{
"tenant_id": "ramesh_auto",
"visibility": "public"
}"the updated artifact row"
POST/artifacts
GET/people?tenant_id=
{
"summary": {
"customers": 5,
"suppliers": 20,
"carriers": 6,
"outstanding": 645400
},
"customers": [
{
"id": "cust-sharma-motors",
"name": "Sharma Motors",
"invoices": 3,
"billed": 152700,
"outstanding": 152700,
"worst_overdue_days": 37,
"defaulter": true
}
],
"suppliers": [
{
"id": "sup-01",
"name": "Balaji Steel Traders",
"category": "raw steel coils",
"trust_score": 4.2
}
],
"carriers": [
{
"id": "car-1",
"name": "VRL Logistics",
"route": "Faridabad→Ludhiana",
"rate_per_kg": 4.5
}
]
}GET/logs?tenant_id=
[
{
"id": "act-1",
"ts": "2026-09-19T02:10:00Z",
"kind": "agent_created",
"text": "Nirmata hired 'Logistics Agent'"
}
]GET/metrics?tenant_id=
{
"runs": 12,
"total_tokens": 48213,
"est_cost_usd": 0.0412,
"avg_latency_ms": 1830,
"by_tool": {
"vasool": 5,
"sourcer": 2
},
"recent": []
}GET/templates?tenant_id=
[
{
"id": "chase-overdue",
"category": "money",
"title": "Chase overdue payments",
"prompt": "Show my overdue invoices and draft a polite reminder for the oldest one.",
"runs_on": "vasool"
},
{
"id": "digital-presence",
"category": "presence",
"title": "Digital presence agent",
"prompt": "I want to sell online — build me an agent that lists on Facebook Marketplace + IndiaMART and keeps listings SEO-optimized.",
"runs_on": "nirmata",
"agent_spec": {
"name": "Digital Presence Agent",
"goal": "Publish products to online marketplaces and keep listings SEO-optimized",
"tools": []
}
}
]POST/templates/{id}/install
{
"tenant_id": "ramesh_auto"
}{
"id": "agent-abc123",
"status": "active",
"created_by": "factory"
}POST/context/upload
multipart/form-data: file=<any> OR text=<note>, tenant_id
{
"id": "doc-1",
"filename": "GSTR-3B_FY25.xlsx",
"kind": "spreadsheet",
"tags": [
"tax",
"finance"
],
"summary": "GSTR-3B filing data for FY25, 18 rows",
"status": "fed_to_agents",
"created_at": "2026-09-20T04:00:00Z"
}GET/context?tenant_id=
[
{
"id": "doc-1",
"filename": "GSTR-3B_FY25.xlsx",
"kind": "spreadsheet",
"tags": [
"tax",
"finance"
],
"summary": "GSTR-3B filing data for FY25",
"status": "fed_to_agents",
"created_at": "2026-09-20T04:00:00Z"
}
]DELETE/context/{id}
{
"status": "deleted"
}POST/onboarding
{
"tenant_id": "ramesh_auto",
"business": {
"name": "Ramesh Auto Components",
"owner": "Ramesh Gupta",
"city": "Faridabad",
"phone": "",
"type": "manufacturer",
"line": "auto components",
"products": "brake pads",
"materials": "steel coils",
"years": 12
},
"prefs": {
"language": "hinglish",
"reminder_tone": "polite",
"approval_mode": "manual",
"notify_email": "[email protected]",
"credit_terms_days": 45,
"uses_gst": true
},
"pains": [
"late_payments",
"gst",
"no_online_presence"
],
"slow_payers": [
"Sharma Motors"
],
"key_buyers": [
"Khanna Industries"
],
"key_suppliers": [
"Balaji Steel"
],
"rules": [
"Big orders go through GST invoice only"
],
"tools_today": [
"excel",
"whatsapp"
],
"auto_hire": true
}{
"tenant_id": "ramesh_auto",
"onboarded": true,
"memories_created": 4,
"agents_installed": [
{
"id": "agent-abc123",
"name": "Collections Agent"
}
],
"suggested_agents": [
{
"template_id": "digital-presence",
"title": "Digital presence agent",
"reason": "no online presence"
}
],
"next_steps": [
"Import your existing ledger from Excel"
]
}GET/approvals?tenant_id=&status=
[
{
"id": "apr-1",
"tool": "create_invoice",
"title": "Add invoice for Kapil Auto (₹12,400)",
"summary": "Invoice ₹12,400 to Kapil Auto, due 2026-10-19",
"agent": "vasool",
"risk": "ask",
"status": "pending|executed|denied|failed",
"args": {},
"created_at": "2026-09-26T04:00:00Z"
}
]POST/approvals/{id}/approve
{
"id": "apr-1",
"status": "executed",
"result": {},
"result_ref": {
"kind": "invoice",
"id": "inv-x",
"label": "INV-2302"
}
}POST/approvals/{id}/deny
{
"id": "apr-1",
"status": "denied"
}POST/approvals/grant
{
"tenant_id": "ramesh_auto",
"tool": "create_invoice",
"on": true
}{
"tool": "create_invoice",
"granted": true,
"grants": [
"create_invoice"
]
}GET/approvals/grants
{
"grants": [
"sync_catalog"
],
"gated_tools": [
"create_artifact",
"create_invoice",
"publish_listing",
"schedule_alert",
"sync_catalog"
]
}POST/alerts/{id}/dismiss
{
"id": "alert-1",
"status": "dismissed"
}GET/roles
[
{
"id": "compliance",
"name": "Compliance Agent",
"hindi_tagline": "कानून का ख्याल",
"category": "compliance",
"icon": "shield",
"description": "Watches GST/TDS deadlines",
"goal": "Track GST/TDS filing deadlines",
"default_tools": [
"list_alerts",
"schedule_alert"
],
"allowed_tools": [
"list_alerts",
"schedule_alert",
"aging_report"
],
"tool_limit": 4,
"max_action": "draft_only",
"extras": [
"artifact",
"memory"
],
"intent_keywords": [
"gst"
]
}
]POST/agents/batch
{
"tenant_id": "ramesh_auto",
"roles": [
{
"role_id": "compliance",
"tools": [
"list_alerts"
]
},
{
"role_id": "digital_presence"
}
]
}{
"hired": [
{
"id": "agent-ab12cd",
"name": "Compliance Agent",
"role_id": "compliance",
"tools": [
"list_alerts"
],
"refused_tools": []
}
],
"errors": [
{
"role_id": "ghost",
"error": "unknown role"
}
]
}POST/integrations/mcp/{id}/test
{
"id": "mcp-1",
"status": "connected",
"tools": [
{
"name": "list_overdue_invoices",
"read_only": true,
"description": "…"
}
],
"last_checked": "2026-09-26T10:00:00Z"
}POST/integrations/mcp/token
{
"token": "<signed, scope=mcp>",
"endpoint_path": "/mcp",
"expires_in_days": 90,
"tools": [
"aging_report",
"create_invoice",
"list_overdue_invoices"
]
}GET/marketplace
{
"mcp": [
{
"id": "custom",
"name": "Any MCP server",
"icon": "mcp",
"category": "custom",
"desc": "…",
"url_hint": "https://…/mcp"
}
],
"installed": [],
"sahayak_mcp_tools": [
"list_overdue_invoices"
]
}POST/scheduler/run
{
"moved": 1
}GET/sent
[
{
"id": "msg-1",
"to": "[email protected]",
"subject": "...",
"via": "console",
"sent_at": "..."
}
]POST/demo/reset
{
"status": "reseeded",
"tenants": [
"ramesh_auto"
]
}POST/context/reembed
{
"model": "amazon.titan-embed-text-v2:0",
"reembedded": 10,
"skipped": 0
}GET/health
{
"status": "ok",
"use_aws": false,
"model": "mock|bedrock|anthropic|openai|ollama|litellm",
"provider": "bedrock",
"orchestrator_model": "apac.amazon.nova-pro-v1:0",
"worker_model": "apac.amazon.nova-lite-v1:0",
"embed_provider": "titan|openai|ollama|none",
"embed_model": "amazon.titan-embed-text-v2:0"
}AWS setup
| Service | Used for |
|---|---|
| Bedrock — Nova Pro / Lite | Orchestrator + specialists (Strands BedrockModel); Nova Lite parses invoice photos |
| Strands Agents SDK | Agent runtime, agents-as-tools orchestration, session managers |
| DynamoDB | All state — 11 tables, PAY_PER_REQUEST, PK tenant_id + SK id |
| S3 | Agent session persistence + invoice uploads |
| SES | Payment reminders & alerts (sandbox = verified recipients only) |
| Lambda + Mangum | Serverless API (handler already wired in main.py) |
| EventBridge | Scheduled alert promotion (replaces the local scheduler thread) |
Environment
USE_AWS=1 AWS_REGION=ap-south-1 ORCHESTRATOR_MODEL=apac.amazon.nova-pro-v1:0 WORKER_MODEL=apac.amazon.nova-lite-v1:0 S3_BUCKET=… # sessions + uploads SES_SENDER=… # must be a verified SES identity DDB_TABLE_*=sahayak-* # 11 tables, created by Ayush # credentials: ~/.aws profile OR AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY
Verify a handoff in one command: USE_AWS=1 python simulation/check_aws.py → creds, tables, bucket, SES sender, Bedrock converse.
Demo script
This is literally simulate_demo.py — if the sim is green, the demo is green.
- 1Reset demo → roster shows Vasool, Sourcer, Khata
- 2"show my overdue invoices" → Sahaayak routes to Vasool, real ₹ amounts
- 3Upload invoice photo → parsed into the ledger
- 4Draft a reminder → approve → sent (SES / console)
- 5"mera transporter nahi aaya" → Nirmata previews a Logistics Agent
- 6"haan, create it" → agent materializes in the roster — HIRED BY AI badge
- 7"cheapest pickup to ludhiana?" → the new agent answers with real carriers
- 8Alerts + cashflow views → "it works while you sleep"
Team & ownership
All UI — landing, dashboard, agent views, chat, calendar, connectors. Builds against contract.json, never waits on backend.
FastAPI surface, agents, store/notifier seams, DynamoDB/SES/S3/Bedrock, deploy. Sees AYUSH.md first.
Merge gate for both: pytest + simulate_demo.py green.