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.
  • InjectGET /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+):

Shell
# 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 dev

Tip

Open the UI at 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

MethodEndpointDescription
GET/api/healthHealth check
GET/api/inject?name=...Inject context (see Inject API)
GET/api/contextsList contexts
GET/api/contexts/:idGet context by ID
POST/api/contextsCreate context
GET/api/agentsList agents
GET/api/agents/:idGet agent by ID
POST/api/agents/registerRegister agent
POST/api/agents/:id/approveApprove agent
POST/api/agents/:id/rejectReject agent
GET/api/organizationsList organizations
POST/api/organizationsCreate organization
GET/api/templatesList templates
GET/api/a2aA2A Agent Card (discovery)
POST/api/a2aA2A skill execution
GET/api/lineageRecent 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.

cURL
# 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/a2a returns 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/a2a with 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:

Well-known URI

The spec recommends serving the Agent Card at /.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
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
# 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.

Example: trading limits template schema
{
  "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
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

.env
# 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=production

Deployment

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.