Documentation
Private betaGuarani AI is in private beta. The packages, endpoints and flags below are the v1 beta interface and may change before general availability. Access tokens are issued to provisioned workspaces.
Overview
Guarani AI gives every release a single, explained verdict. It has three modules that work on their own or together.
- Verify
- AI code review and architecture compliance on every pull request: semantic review, performance budgets, API contract checks and generated tests.
- Mesh
- An OpenAI-compatible gateway in front of Azure OpenAI, Amazon Bedrock, Google Vertex AI and open-weight models on dedicated GPUs, with routing policies, failover, caching and per-team budgets.
- Mobile CI
- End-to-end UI and regression suites on real Android and iOS devices, started from your existing pipelines.
Concepts
- Workspace
- Your organization's tenant: members, access tokens, policies, data region and retention.
- Project
- One repository connected to a workspace, configured by its
guarani.yml. - Profile
- A named set of checks and gates, for example
pull-requestorrelease. - Run
- One execution of a profile, a Mesh query or a mobile suite, with its logs and artifacts.
- Verdict
- The result of a run:
pass,advisoryorfail, with the findings that explain it.
Quickstart
Three commands take a repository from nothing to a first verdict. You need a workspace access token, issued when your trial workspace is provisioned.
npm i -g @guarani-ai/cli
guarani login
guarani verify --repo acme/core-api --profile pull-requestguarani login stores the token in your operating system keychain. In CI, set GUARANI_TOKEN instead.
Install the CLI
The CLI is distributed on npm as @guarani-ai/cli. It requires Node.js 20 or later and runs on Linux, macOS and Windows.
npm i -g @guarani-ai/cli
guarani --versionConfiguration
guarani init creates guarani.yml at the root of the repository. It declares profiles, performance budgets, the Mesh policy and providers, and the mobile suites and devices.
# guarani.yml
version: 1
project: acme/core-api
profiles:
pull-request:
checks: [architecture, contracts, performance]
tests: generate-missing
block_on: [fail]
release:
checks: [architecture, contracts, performance, tests]
mobile: checkout
block_on: [fail, advisory]
budgets:
latency_p95_ms: 450
memory_mb: 512
mesh:
policy: balanced # latency | balanced | cost
providers: [azure-openai, amazon-bedrock, google-vertex-ai, gpu-open-weight]
residency: us # us | eu
daily_budget_usd:
payments: 66
search: 60
mobile:
suites:
checkout:
framework: maestro
path: e2e/checkout
devices: [pixel-8, iphone-15, galaxy-s24]
retries: 1Profiles are selected with --profile. block_on sets which verdicts fail the check in your pipeline.
CLI reference
Every command accepts --help. Commands exit with code 1 when the verdict matches the profile's block_on list.
| Command | What it does |
|---|---|
guarani login | Authenticate with a workspace access token. |
guarani init | Create guarani.yml from the languages, services and API contracts detected in the repository. |
guarani verify | Run a verification for a repository and profile, and report the verdict. |
guarani mesh stats | Show traffic share, latency and spend by provider or team for a time window. |
guarani mesh route | Explain which provider and region a sample request would be routed to, without sending it. |
guarani mobile run | Run a mobile suite on real devices and attach video, logs and network traces. |
guarani runs list | List recent runs with their status and verdict. |
| Flag | Description |
|---|---|
--repo <owner/name> | Repository to run against. Defaults to the Git remote of the current directory. |
--profile <name> | Profile from guarani.yml, for example pull-request or release. |
--report <github|gitlab|markdown> | Publish the result as a GitHub check, a GitLab merge request note, or Markdown on stdout. |
--json | Print machine-readable JSON instead of the human-readable log. |
# Install the CLI (Node.js 20 or later)
npm i -g @guarani-ai/cli
# Authenticate with your workspace access token
guarani login
# Create guarani.yml for this repository
guarani init
# Run the release profile and print a JSON report
guarani verify --repo acme/core-api --profile release --jsonGitHub Actions
Add a workflow that runs on pull_request. Store the workspace token as the repository secret GUARANI_TOKEN. The checks: write permission lets the CLI post the verdict as a check.
name: guarani
on: pull_request
permissions:
contents: read
checks: write
pull-requests: write
jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm i -g @guarani-ai/cli
- run: guarani verify --profile pull-request --report github
env:
GUARANI_TOKEN: ${{ secrets.GUARANI_TOKEN }}GitLab CI
Add a job that runs on merge request pipelines. Store the workspace token as a masked CI/CD variable named GUARANI_TOKEN.
guarani-verify:
stage: test
image: node:20
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
script:
- npm i -g @guarani-ai/cli
- guarani verify --profile pull-request --report gitlab
# GUARANI_TOKEN is a masked CI/CD variable in the project settingsREST API
Base URL: https://api.guarani-llc.com/v1. Authenticate with Authorization: Bearer <token>. Requests and responses are JSON.
| Method | Path | Purpose |
|---|---|---|
POST | /v1/verifications | Start a verification for a repository, ref and profile. |
GET | /v1/verifications/{id} | Get the status, verdict and findings of a verification. |
POST | /v1/mesh/chat/completions | OpenAI-compatible chat completions, routed by Mesh. |
GET | /v1/mesh/usage?group_by=team | Token usage and spend, grouped by team, provider or model. |
POST | /v1/mobile/runs | Start a mobile suite on a set of devices. |
GET | /v1/mobile/runs/{id}/artifacts | List the video, device logs and network traces of a run. |
Start a verification
curl https://api.guarani-llc.com/v1/verifications \
-H "Authorization: Bearer $GUARANI_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 7c1d9e2a-1842-release" \
-d '{"repo": "acme/core-api", "ref": "refs/pull/1842/head", "profile": "release"}'Response 202 Accepted:
{
"id": "ver_01JB7Q4M2XK8",
"status": "queued",
"repo": "acme/core-api",
"ref": "refs/pull/1842/head",
"profile": "release",
"created_at": "2026-10-25T14:02:11Z",
"links": {
"self": "https://api.guarani-llc.com/v1/verifications/ver_01JB7Q4M2XK8"
}
}Mesh chat completions
The Mesh endpoint follows the OpenAI chat completions format, so existing OpenAI client libraries work by changing the base URL to https://api.guarani-llc.com/v1/mesh. Use "model": "auto" to let the policy choose, or name a model your workspace allows. metadata.team attributes spend to a team budget.
curl https://api.guarani-llc.com/v1/mesh/chat/completions \
-H "Authorization: Bearer $GUARANI_TOKEN" \
-H "Content-Type: application/json" \
-d '{"model": "auto", "messages": [{"role": "user", "content": "Summarize this diff"}], "metadata": {"team": "payments"}}'Errors
Errors use standard HTTP status codes and a JSON body with a stable type, a readable message and the request_id to quote when you contact support.
{
"error": {
"type": "invalid_request",
"message": "Profile 'release' is not defined in guarani.yml.",
"request_id": "req_7Q2M9X4K1B"
}
}Rate limits and retries
Every response carries RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset. A 429 response includes Retry-After in seconds. Send an Idempotency-Key header on POST requests: a retry with the same key within 24 hours returns the original response instead of starting a second run.
Webhooks
Workspaces can subscribe to verification.completed, mobile.run.completed and mesh.budget.threshold. Each delivery is signed with HMAC-SHA256 using your webhook secret, in the Guarani-Signature header (t=<timestamp>,v1=<signature>, computed over <timestamp>.<raw body>). Reject deliveries older than five minutes.
import hashlib
import hmac
def is_valid(secret: bytes, body: bytes, header: str) -> bool:
# header looks like: t=1761400931,v1=5f2b...
parts = dict(item.split("=", 1) for item in header.split(","))
signed = parts["t"].encode() + b"." + body
expected = hmac.new(secret, signed, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, parts["v1"])SDKs
Typed SDKs wrap the same REST endpoints, with retries, idempotency keys and pagination handled for you.
TypeScript
npm i @guarani-ai/sdkimport { Guarani } from "@guarani-ai/sdk";
const guarani = new Guarani({ token: process.env.GUARANI_TOKEN });
const run = await guarani.verifications.create({
repo: "acme/core-api",
ref: "refs/pull/1842/head",
profile: "release",
});
// Polls until the verdict is ready
const result = await guarani.verifications.wait(run.id);
console.log(result.verdict, result.findings.length);Python
pip install guarani-aiimport os
from guarani_ai import Guarani
client = Guarani(token=os.environ["GUARANI_TOKEN"])
run = client.verifications.create(
repo="acme/core-api",
ref="refs/pull/1842/head",
profile="release",
)
# Polls until the verdict is ready
result = client.verifications.wait(run.id)
print(result.verdict, len(result.findings))Support
Write to sylvain@guarani-llc.com. Include the request_id from any error response and the run ID when a run is involved. During the private beta, provisioned workspaces get answers from the engineer who builds the product.