Developer documentation
Integration and usage guide for developers and anyone in the firm. Use Sandarb for AI governance: approved context, prompts, audit trail, and agent registry.
Overview
Sandarb is an AI governance platform: a single place for approved prompts and context, audit trail, lineage, and a living agent registry. Your AI agents and applications integrate via API, A2A, or Inject API. Sandarb also runs as an A2A agent so other agents can call it for validation and approved context.
- API – CRUD for organizations, agents, contexts, templates; inject context by name.
- A2A – Discovery (Agent Card) and skills:
get_context,validate_context,get_lineage,register. - Inject –
GET /api/inject?name=...returns approved context (JSON/YAML/text) for your agent. - Git-like – Propose revisions; approve/reject in the UI. Version history for compliance.
Quick start
Run Sandarb locally (Node 18+):
# Clone and install
git clone https://github.com/openint-ai/sandarb.ai.git
cd sandarb.ai
npm install
# Optional: Postgres (demo data seeded on start)
export DATABASE_URL=postgresql://postgres:sandarb@localhost:5432/sandarb-dev
# Start (UI on 4000, API on 4001)
./scripts/start-sandarb.sh
# Or: npm run devTip
http://localhost:4000. Sign in to see the dashboard, organizations, agents, and contexts.API
Base URL: same origin as the UI (e.g. https://ui.sandarb.ai). When running locally with two servers, set NEXT_PUBLIC_API_URL=http://localhost:4001 so the UI calls the API port.
Core endpoints
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/health | Health check |
| GET | /api/inject?name=... | Inject context (see Inject API) |
| GET | /api/contexts | List contexts |
| GET | /api/contexts/:id | Get context by ID |
| POST | /api/contexts | Create context |
| GET | /api/agents | List agents |
| GET | /api/agents/:id | Get agent by ID |
| POST | /api/agents/register | Register agent |
| POST | /api/agents/:id/approve | Approve agent |
| POST | /api/agents/:id/reject | Reject agent |
| GET | /api/organizations | List organizations |
| POST | /api/organizations | Create organization |
| GET | /api/templates | List templates |
| GET | /api/a2a | A2A Agent Card (discovery) |
| POST | /api/a2a | A2A skill execution |
| GET | /api/lineage | Recent context deliveries (lineage) |
All mutations and inject support optional audit headers (see Audit headers).
Inject API
Your AI agent or application fetches approved context by name. Sandarb returns the content and logs the request for lineage.
# By name (recommended)
GET /api/inject?name=ib-trading-limits
# By name + format
GET /api/inject?name=my-context&format=json
GET /api/inject?name=my-context&format=yaml
GET /api/inject?name=my-context&format=text
# Variable substitution (if context has {{variable}} placeholders)
GET /api/inject?name=my-context&vars={"user_id":"123"}Optional headers: X-Sandarb-Agent-ID, X-Sandarb-Trace-ID, X-Sandarb-Variables (JSON).
A2A protocol
The Agent2Agent (A2A) Protocol is an open standard (see references below) that enables communication and interoperability between AI agents built on different frameworks and by different vendors. A2A allows agents to discover each other's capabilities, negotiate interaction modalities, manage collaborative tasks, and securely exchange information without accessing each other's internal state or tools.
Sandarb as an A2A Server: Sandarb implements the A2A protocol as an A2A Server (Remote Agent). Your AI agents act as A2A Clients when they call Sandarb for governance: they discover Sandarb via its Agent Card and invoke skills to get approved context, validate content, retrieve lineage, or register.
How A2A URLs work in practice
- Discovery – Agent A uses the A2A URL of Agent B to read its capabilities (e.g.
GET /api/a2areturns the Agent Card). - Interaction – Agent A sends a JSON-RPC 2.0 message over HTTP(S) to that URL to initiate a task (e.g.
POST /api/a2awith method and params). - Real-time updates – For long-running tasks, the A2A server may use Server-Sent Events (SSE) to send updates back to the client. Sandarb currently responds synchronously; SSE may be added for streaming or long-running flows.
Specification & key concepts
For the full protocol specification and terminology (Agent Card, Task, Message, Part, Artifact, transport over HTTP/JSON-RPC, streaming, security), use the official resources:
- A2A Protocol Specification (Google) – transport, Agent Card structure, RPC methods, data objects.
- Key concepts – A2A Client, A2A Server, Agent Card, Task, Message, Part, Artifact.
Well-known URI
/.well-known/agent.json. Sandarb exposes its Agent Card at GET /api/a2a for convenience and consistency with the rest of the API.Discovery (Agent Card)
Clients discover Sandarb by fetching its Agent Card. The response is a JSON document describing the agent's name, description, service URL, version, capabilities, and skills.
curl -s "https://ui.sandarb.ai/api/a2a"Returns the Agent Card with name, description, url, version, capabilities, and skills (get_context, validate_context, get_lineage, register).
Skill invocation
A2A Clients send HTTP POST requests to Sandarb's A2A endpoint with a JSON body specifying the skill and input. Sandarb processes the request and returns a JSON-RPC-style response. All context requests are logged for lineage and audit.
# POST /api/a2a
# Content-Type: application/json
# Body: { "skill": "get_context", "input": { "name": "ib-trading-limits" } }
# Skills offered by Sandarb (governance):
# - get_context – Retrieve approved context by name (lineage logged)
# - validate_context – Validate context content against policy
# - get_lineage – Recent context deliveries for an agent/trace
# - register – Register an agent (manifest: agent_id, version, owner_team, url)For production, use HTTPS and follow the specification's authentication and security guidance (e.g. credentials via HTTP headers, TLS).
Contexts & agents
Contexts are named, versioned blobs of configuration (e.g. trading limits, suitability policy). Create and edit in the UI or via API. Use Inject or A2A get_context to pull into your agent.
Agents are registered in Sandarb (by manifest ping or API). Approved agents can request context; unregistered agents can be blocked by policy. Register via POST /api/agents/register or A2A register skill with a manifest.
Organizations – Root org is created on first run. Create sub-orgs and attach agents to them.
Templates for context
Templates define a reusable structure for context content. Each template has a schema (JSON Schema describing the shape of context content) and optional default values. When you create a context, you can link it to a template via templateId so the context follows that structure.
Why templates help:
- Consistency – All contexts of the same type (e.g. trading limits) share the same fields and types so agents and validators can rely on a known shape.
- Governance – Linking a context to a template documents which schema it conforms to, supporting compliance and audit.
- Faster authoring – New contexts can be pre-filled from a template's default values and guided to include the right fields.
Sample templates (seeded via POST /api/seed): compliance policy, trading limits, suitability policy, KYC config, disclosure policy. View them under Templates in the app or GET /api/templates.
{
"type": "object",
"properties": {
"policy": { "type": "string", "description": "Policy name" },
"varLimit": { "type": "number", "description": "VAR limit" },
"singleNameLimit": { "type": "number", "description": "Single-name limit" },
"effectiveDate": { "type": "string" }
},
"required": ["policy"]
}Audit headers
Optional headers for inject and API calls so Sandarb can record lineage (who requested what, when):
X-Sandarb-Agent-ID– Identifier of the calling agent.X-Sandarb-Trace-ID– Request/correlation ID for tracing.
Example
curl -H "X-Sandarb-Agent-ID: my-agent" -H "X-Sandarb-Trace-ID: req-123" "https://ui.sandarb.ai/api/inject?name=my-context"Environment variables
# Database (optional; default: SQLite at ./data/sandarb.db)
DATABASE_URL=postgresql://user:pass@host:5432/sandarb-dev
# When UI and API run on different ports (e.g. 4000 and 4001)
NEXT_PUBLIC_API_URL=http://localhost:4001
# Server
PORT=3000
NODE_ENV=productionDeployment
Docker: build and run with docker compose up -d (Postgres + app). Demo data is seeded on container start when DATABASE_URL is set.
GCP Cloud Run: use ./scripts/deploy-gcp.sh PROJECT_ID. See docs/deploy-gcp.md for permissions, Cloud SQL, and IAM.