I built an open-source agent runtime that connects AI to SAP B1 via WhatsApp
The problem I was solving
I work as a SAP Business One consultant. Every day I watch managers open the SAP client, navigate through five screens, run a report, export to Excel, and send it on WhatsApp.
The data was always there. The friction was the interface.
So I built Capyra: an autonomous agent runtime that lives in WhatsApp and acts on business systems directly.
What it does
Your team sends a WhatsApp message:
"How many open orders do we have today?"
Capyra queries SAP B1 via Service Layer REST API and replies in seconds:
"7 orders pending approval, total R$ 48,320.
Oldest: order #4821 from Acme Corp, waiting 3 days.
Want me to send a reminder to the approvers?"
No dashboards. No reports. No IT ticket.
Architecture
WhatsApp (Evolution API)
↓
Capyra Gateway (WebSocket)
↓
Agent Loop (Claude / GPT)
↓
Skills (SAP B1, HTTP, Postgres...)
↓
Three-layer Memory (pgvector)
↓
Immutable Event Store
The agent loop is simple: perceive → plan → act. Each action is recorded as an immutable event. Write operations always require user confirmation.
The Skills system
Skills are directories with two files:
SKILL.md — instructions for the LLM:
# SAP Business One Skill
## Available Tools
### sap_get_orders
Retrieve sales orders with filters...
## Behavior Rules
- Always confirm before write operations
- Format currency as R$ X.XXX,XX
index.ts — tool implementation:
export class SapB1Skill implements SkillExecutor {
tools = [...]
async execute(toolName: string, params: Record<string, unknown>) {
// your SAP B1 Service Layer calls here
}
}
Any developer can build and share a skill for any system.
Three-layer memory
One of the most interesting parts of Capyra is how it handles memory:
Episodic — last N messages per session. Simple context window.
Semantic — business facts stored as vector embeddings (pgvector). When a message arrives, relevant facts are retrieved by similarity and injected into the prompt.
Procedural — learned preferences per workspace. The agent learns things like "this client always orders in multiples of 50" and stores them as key-value pairs with confidence scores.
Audit trail
Every agent action is an immutable event in PostgreSQL:
SELECT occurred_at, type, tool_name, approved_by
FROM agent_events
ORDER BY occurred_at;
-- message_in → user sent a message
-- decision → LLM decided to call a tool
-- tool_call → tool was called
-- approval_required → user confirmation requested
-- approved → user confirmed
-- tool_result → tool returned data
-- message_out → agent responded
This is critical for enterprise use: you can replay exactly what the agent did and why.
Docker
No Node.js required — just Docker.
curl -O https://raw.githubusercontent.com/marcostaira/capyra/main/docker-compose.hub.yml
curl -O https://raw.githubusercontent.com/marcostaira/capyra/main/.env.example
cp .env.example .env
# edit .env with your values
docker compose -f docker-compose.hub.yml up -d
Images on Docker Hub:
marcostaira/capyra-gatewaymarcostaira/capyra-whatsapp
Getting started
Option 1 — CLI (Node.js required):
npm install -g @capyra/cli
capyra init my-company
cd my-company
npm start
Option 2 — Docker only:
curl -O https://raw.githubusercontent.com/marcostaira/capyra/main/docker-compose.hub.yml
cp docker-compose.hub.yml .env.example .env
docker compose -f docker-compose.hub.yml up -d
Both options set up PostgreSQL, Gateway, WhatsApp channel and SAP B1 connector automatically.
What's next
- Telegram and Slack channels
- Skills marketplace
- Agent-to-Agent (A2A) protocol
- Computer Use skill for systems without API
- Totvs / Omie connectors
Links
- GitHub: github.com/marcostaira/capyra
- npm: npmjs.com/package/@capyra/cli
Built in Brazil 🇧🇷 · MIT License · Capybara mascot 🦫
Top comments (0)