# Volkom Mesh Telemetry — User Guide

This guide explains, in plain language, **how an agent sends telemetry to
Volkom Mesh**. There are two independent channels:

1. **Execution** (what the agent *did*): start, steps, end, errors, timings.
2. **Business** (the customer's *KPIs*): money, quantities, percentages and
   times that matter to the business (sales, invoices, customers served, etc.).

Both channels live in **the same API** and are stored in **a single database**
per tenant. The customer portal and Volkom's admin panel read exactly the same
data from there.

---

## Concepts in 1 minute

| Concept | What it is |
|---------|------------|
| **Tenant** | The customer (e.g. `shopflow`). Has its own isolated database. |
| **Agent** | A program that performs a task (e.g. `sales-monitor`). |
| **Run** | One execution of the agent, identified by a unique `run_id`. |
| **Event** | Each thing that happens in a run: it started, did a step, finished. |
| **KPI** | A business number the agent reports (sales, % success…). |
| **Token** | The credential (Bearer) the agent authenticates with. |

> **The golden rule:** a run is a sequence of events sharing the same
> `run_id`. It begins with a `started` event, may have several `in_progress`
> (the steps), and closes with `completed` or `failed`.

---

## Channel 1 — EXECUTION telemetry

Tells the story of what the agent did. Each event can carry as much detail as
you want — from something minimal to a rich step-by-step narrative.

### The dimensions of an event

All of them are **optional** except the basics. Fill in what makes sense for your agent:

| Dimension | What it's for | Example |
|-----------|---------------|---------|
| `message` | Human description of the step | "Downloaded the email attachment" |
| `level` | Importance/color | `info`, `warning`, `error`, `success`, `debug` |
| `category` | Groups steps by phase | "Email", "Processing", "Close" |
| `metrics` | Measurable numbers (chartable) | `{"emails": 11, "rows": 1240}` |
| `links` | External references | URL of a document, an order, a dashboard |
| `source` | Technical origin | `email_skills.py:474` |
| `seq` | Order of the step within the run | 1, 2, 3… |

> **Guiding principle:** the frontend is **generic**. It shows whatever you
> send, with no custom code. If you add a new KPI or category, it appears on its
> own — no UI changes needed.

### What a typical run looks like

```
▸ started                                        (the run begins)
  · Searched emails        cat: Email         {emails: 11}
  · Downloaded attachment  cat: Email
  ⚠ Parse retry            cat: Processing    level: warning
  · Consolidated data      cat: Processing    {customers: 15}
  · Uploaded to Drive      cat: Close         link: https://drive…
■ completed                                      (closes OK)
```

---

## Channel 2 — BUSINESS telemetry (KPIs)

Beyond *what it did*, the agent can report **how much it was worth** to the
business. This feeds the executive dashboard (cards, trends, comparisons).

### A KPI is defined by 4 things

| Field | What it is | Example |
|-------|------------|---------|
| `key` | Internal identifier | `revenue` |
| `label` | Visible name | "Revenue" |
| `unit` | How it is formatted | see table below |
| `agg` | How it totals over a period | see table below |

### Available units (`unit`)

| Unit | Displayed as | Example |
|------|--------------|---------|
| `count` | number | 1,240 |
| `money:<ISO>` | currency | `money:USD` → US$ 9,500 · `money:ARS` → $ 1,200,000 |
| `percent` | percentage | 3.4 % |
| `duration` | time (the value is given in seconds) | 2 h 15 min |

### Available aggregations (`agg`) — how it adds up over the selected period

| Agg | What it does | Use for |
|-----|--------------|---------|
| `sum` | adds everything | sales, invoices, units |
| `last` | takes the latest value | current stock, MRR, % occupancy |
| `avg` | average | average wait time |
| `max` | the maximum | usage peak |

> **Why `agg` matters:** if you report "sales = 100" in 30 runs and the
> aggregation is `sum`, the period shows 3,000. If it were `last` (e.g. stock),
> it would show only the latest: 100. Picking the wrong `agg` gives wrong
> numbers on the dashboard.

---

## The two ways to send telemetry

### Option A — With the carcass (recommended for Python agents)

If your agent uses `volkom-core`, **you never touch HTTP**: subclass `BaseAgent`
and call methods. The carcass builds the events, sends them and manages the
run lifecycle.

```python
from volkom_core import BaseAgent, AgentResult, KPI

class SalesMonitor(BaseAgent):
    agent_name = "sales-monitor"
    agent_version = "1.0.0"
    description = "Monitors daily sales."
    # Business KPIs this agent reports:
    business_kpis = [
        KPI("orders",  "Orders",  "count",     "sum"),
        KPI("revenue", "Revenue", "money:USD", "sum"),
    ]

    def run(self) -> AgentResult:
        # --- EXECUTION telemetry (steps) ---
        self.event("Connected to the store", category="Ingest")
        self.event("Read orders", category="Ingest", metrics={"orders": 42})
        self.warn("3 orders without address", category="Validation",
                  metrics={"incomplete": 3})

        # --- BUSINESS telemetry (KPIs) ---
        self.kpi("orders", 42)
        self.kpi("revenue", 9500)

        return AgentResult(records_processed=42)
```

`started`, `completed`/`failed`, timings and the `run_id` are set by the
carcass on its own when the agent runs. You only describe what happens.

**Carcass methods:**
- `self.event(message, level=, category=, metrics=, links=, source=)` — a rich event.
- `self.step(msg)` / `self.info(msg)` / `self.warn(msg)` / `self.error(msg)` — per-level shortcuts.
- `self.kpi(key, value)` — reports a business KPI (must be declared in `business_kpis`).
- `self.emit_metric(key, value)` — free metadata on the closing event (not a chartable KPI).

### Option B — Direct HTTP (any language)

If your agent isn't Python or you want to control the HTTP yourself, call the
API directly. The exact endpoints, headers and JSON are in the
**[API Reference](../api/)** (written to be processed by Claude Code or a developer).

In short, it's 3 calls:
1. `POST /api/v1/agents/register` — declares the agent and its KPIs (once).
2. `POST /api/v1/telemetry` — one execution event (one per started/step/close).
3. `POST /api/v1/telemetry/business` — the KPIs of a run.

All with the header `Authorization: Bearer <agent-token>`.

---

## Common mistakes (and how to avoid them)

- **All steps share the `run_id`.** If every event uses a different `run_id`,
  the portal sees them as separate runs and the narrative is lost.
- **Always close the run** with `completed` or `failed`. A run without a close
  shows as "in progress" forever.
- **Declare KPIs before using them** (`business_kpis` / `register`). If you send
  an undeclared KPI, the value gets in but the dashboard doesn't know its unit/agg.
- **Choose `agg` carefully.** `sum` for things that accumulate, `last` for states.
- **Level drives color.** Use `warning`/`error` so problems stand out in
  red/amber in the activity view.

---

## Where do I see the telemetry?

- **Customer portal**: the **Activity** screen (grouped runs; expand one to
  see its steps) + the business **Dashboard** (cards with the KPIs).
- **Volkom admin panel**: **Runs** per tenant (same data, technical view)
  + **Audit Log** (who did what on the platform).

Both read the **same API and the same database**. What the agent sends once
shows up on both sides.
