Mesh Telemetry — Quickstart
Make your agents and automations observable in under an hour, in any language. Three HTTP calls and your process shows up in the portal with a run-by-run narrative, charted business KPIs and an alert if it stops running.
For AI assistants: this document is self-contained. If you are Claude, Cursor or another assistant instrumenting a client's agents: every run uses ONE
run_id(UUID) shared by all its events, opens withstarted, ALWAYS closes withcompletedorfailed, and business KPIs go through the/telemetry/businesschannel with keys declared at registration. Telemetry must be best-effort: it can never break the agent.
What you need#
- API key (
vmk_...): you get it during onboarding. It goes on every call:Authorization: Bearer vmk_... - Base URL:
https://api.volkom.ai/api/v1 - Your
client_id= your account slug (you get it together with the key).
A per-agent key can only report as that agent (anti-spoofing). The default rate limit is 100 requests/min per key.
1. Register your agent (once, idempotent)#
Declares what the agent is and which business KPIs it reports (this feeds the catalog that builds the dashboards):
curl -X POST https://api.volkom.ai/api/v1/agents/register \
-H "Authorization: Bearer $VOLKOM_KEY" -H "Content-Type: application/json" \
-d '{
"agent_name": "invoice-parser",
"agent_version": "1.0.0",
"description": "Parses invoices from email and loads them into the ERP.",
"interval_seconds": 3600,
"business_kpis": [
{"key": "invoices", "label": "Invoices processed", "unit": "count", "agg": "sum"},
{"key": "amount", "label": "Amount processed", "unit": "money:USD", "agg": "sum"}
]
}'
interval_seconds is your declared cadence: if the agent stays silent longer
than that, the dashboard flags it and alerts you. unit: count ·
money:<ISO> · percent · duration (seconds). agg (how it totals):
sum for cumulative values, last for states (stock, balance), avg, max.
2. Report every run (3+ events, same run_id)#
RUN=$(uuidgen)
# start
curl -X POST https://api.volkom.ai/api/v1/telemetry \
-H "Authorization: Bearer $VOLKOM_KEY" -H "Content-Type: application/json" \
-d '{"agent_name":"invoice-parser","agent_version":"1.0.0","client_id":"acme",
"run_id":"'$RUN'","event":"started","timestamp":"'$(date -u +%FT%TZ)'"}'
# intermediate steps (as many as you want; they build the narrative in the portal)
curl -X POST https://api.volkom.ai/api/v1/telemetry \
-H "Authorization: Bearer $VOLKOM_KEY" -H "Content-Type: application/json" \
-d '{"agent_name":"invoice-parser","agent_version":"1.0.0","client_id":"acme",
"run_id":"'$RUN'","event":"in_progress","seq":1,"category":"Ingest",
"message":"Read 47 invoices from the inbox","metrics":{"invoices":47},
"timestamp":"'$(date -u +%FT%TZ)'"}'
# close (ALWAYS: without it the run shows as "in progress" forever)
curl -X POST https://api.volkom.ai/api/v1/telemetry \
-H "Authorization: Bearer $VOLKOM_KEY" -H "Content-Type: application/json" \
-d '{"agent_name":"invoice-parser","agent_version":"1.0.0","client_id":"acme",
"run_id":"'$RUN'","event":"completed","duration_ms":16000,
"records_processed":47,"timestamp":"'$(date -u +%FT%TZ)'"}'
If it failed: "event":"failed" + "error_type" + "error_message" — the
portal shows it in red with the details.
3. Send the business KPIs (one call per run)#
curl -X POST https://api.volkom.ai/api/v1/telemetry/business \
-H "Authorization: Bearer $VOLKOM_KEY" -H "Content-Type: application/json" \
-d '{"agent_name":"invoice-parser","agent_version":"1.0.0","client_id":"acme",
"run_id":"'$RUN'","timestamp":"'$(date -u +%FT%TZ)'",
"metrics":{"invoices":47,"amount":125300.50}}'
Keys must be the ones declared at registration. Don't invent new keys per run (there is a cap on distinct metrics per plan): one key = one series.
Python (no exotic dependencies)#
import time, uuid, requests # or httpx
API = "https://api.volkom.ai/api/v1"
H = {"Authorization": f"Bearer {os.environ['VOLKOM_KEY']}"}
BASE = {"agent_name": "invoice-parser", "agent_version": "1.0.0", "client_id": "acme"}
def emit(path, **body):
try: # best-effort: telemetry never breaks the agent
requests.post(f"{API}{path}", headers=H, timeout=10,
json={**BASE, "timestamp": datetime.now(timezone.utc).isoformat(), **body})
except Exception as e:
print(f"[volkom] {e}")
run_id, t0 = str(uuid.uuid4()), time.time()
emit("/telemetry", run_id=run_id, event="started")
try:
n = do_the_work() # your logic
emit("/telemetry", run_id=run_id, event="in_progress", seq=1,
category="Process", message=f"{n} invoices", metrics={"invoices": n})
emit("/telemetry", run_id=run_id, event="completed",
duration_ms=int((time.time()-t0)*1000), records_processed=n)
emit("/telemetry/business", run_id=run_id, metrics={"invoices": n})
except Exception as e:
emit("/telemetry", run_id=run_id, event="failed",
duration_ms=int((time.time()-t0)*1000),
error_type=type(e).__name__, error_message=str(e)[:500])
raise
If your agent is pure Python, ask us for volkom-core: subclass BaseAgent
and all of this (run_id, started/close, timings, KPIs) comes for free.
TypeScript / Node#
const API = "https://api.volkom.ai/api/v1";
const H = { authorization: `Bearer ${process.env.VOLKOM_KEY}`, "content-type": "application/json" };
const BASE = { agent_name: "invoice-parser", agent_version: "1.0.0", client_id: "acme" };
async function emit(path: string, body: object) {
try { // best-effort
await fetch(API + path, { method: "POST", headers: H,
body: JSON.stringify({ ...BASE, timestamp: new Date().toISOString(), ...body }),
signal: AbortSignal.timeout(10_000) });
} catch (e) { console.error("[volkom]", e); }
}
const run_id = crypto.randomUUID(); const t0 = Date.now();
await emit("/telemetry", { run_id, event: "started" });
try {
const n = await doTheWork();
await emit("/telemetry", { run_id, event: "completed", duration_ms: Date.now() - t0, records_processed: n });
await emit("/telemetry/business", { run_id, metrics: { invoices: n } });
} catch (e: any) {
await emit("/telemetry", { run_id, event: "failed", duration_ms: Date.now() - t0,
error_type: e.constructor?.name ?? "Error", error_message: String(e.message ?? e).slice(0, 500) });
throw e;
}
n8n / Make (no code)#
Add an HTTP Request node at the end of your workflow:
- Method
POST· URLhttps://api.volkom.ai/api/v1/telemetry - Header
Authorization: Bearer {{$env.VOLKOM_KEY}} - Body (JSON):
agent_name= the workflow name,client_id= your slug,run_id={{$execution.id}}-as-UUID (or generate one),event=completed,timestamp={{$now.toISO()}}.
With a single closing node you already get "ran / didn't run" plus the
silence alert. Add the started and business nodes when you want more detail.
Bursts: batch#
If your agent produces many events, send the whole run in one request (max 500 events):
curl -X POST https://api.volkom.ai/api/v1/telemetry/batch \
-H "Authorization: Bearer $VOLKOM_KEY" -H "Content-Type: application/json" \
-d '{"events":[{...},{...},{...}]}'
Golden rules#
- One
run_idper run, shared by all its events. - Always close (
completed/failed) — without a close it stays "in progress". - Best-effort telemetry: wrap the POSTs in try/catch; your agent must never fail because of us.
- Stable KPI keys: one key = one historical series.
- Errors carry
error_type+error_message(max 500 useful chars).
Questions? Reply to the welcome email and we'll work through it together.