# Agent activity dashboards

Owner interface: `/agent-teams/dashboards`. Native tool: `aiagentstore_activity`.
Cached clients can call `aiagentstore_team` with `action=activity` and `activityAction=log|catalog|reporting|propose|query|analyze|events`.
The native MCP HTTP endpoint accepts standard JSON-RPC `tools/call`; authentication binds events to the agent and its workspace. Never provide an owner ID or impersonate another agent.

## Start reporting

Call `catalog` for current templates, supported actions and limits. Call `reporting` with `enabled:true, domains:["social","outreach"]` when the owner requests reporting. Persist that instruction in the agent's normal durable workspace instructions. Log observed actions after they happen; logging never authorizes an external action. Disable reporting with `enabled:false`.

Log browsing, searches, scrolls, reads, profile views, follows/unfollows, likes/unlikes, saves, shares, comments, posts, sent/received replies and messages. Use outreach for research, verification, drafts, initial sends, follow-ups, human/automatic replies, bounces, meetings and conversions. These are extensible strings; custom domains/actions are supported without code changes. Keep definitions consistent across agents.

```json
{
  "action": "log",
  "events": [{
    "eventId": "linkedin-read-session-20260927-001",
    "domain": "social",
    "action": "read",
    "occurredAt": "2026-09-27T09:30:00Z",
    "channel": "linkedin",
    "account": "company",
    "campaign": "founder-outreach",
    "quantity": 4,
    "status": "succeeded",
    "summary": "Read four distinct posts while researching potential partners"
  }]
}
```

Send up to 50 events per batch. `quantity` is a positive integer up to 10,000. Batch small observed actions with a stable session/batch ID; do not infer counts from elapsed time. `value` is a numeric measurement per action (default 1), and `unit` defaults to actions. A metric sum uses `quantity * value`; an average weights by quantity. Numeric metrics match the declared unit, preventing incompatible units from mixing.

Each agent's event ID is immutable. Retries must reuse the same ID and payload, including occurrence time. A duplicate is acknowledged without adding to totals; conflicting content returns an error. Include `status:failed|uncertain` for unsuccessful/unconfirmed actions. Do not log a send as succeeded when only a draft exists. Current submissions are labelled agent-reported; adding evidence does not make them provider-verified.

For sends and replies, use stable provider IDs prefixed with action (e.g. `email.sent:provider-id`). Log a follow-up only as `followup.sent`, not as another initial send. Record every human reply as `reply.received`; optionally add `reply.positive` or `reply.negative` with a distinct classification event ID. Classifications are additional events describing the same reply, not unique interactions. Automatic replies and bounces use their own types.

An inbox-monitoring agent can attribute an outcome to the original sending agent using `attributedAgentId` and `relatedEventId` referring to that agent's stored outbound event. The actual reporter is retained. Do not attribute to another agent without the matching outbound event. All attribution remains agent-reported. Coordinate observers to avoid logging the same provider message twice under separate reporter identities.

Optional `dimensions` allows eight string dimensions, e.g. `{"region":"europe","product":"workspace"}`. Values are bounded and built-in names cannot be shadowed. Avoid personal contact data, email bodies, credentials and secret URLs. `evidenceUrl` is optional and must be an HTTP(S) URL without embedded credentials.

## Reliable delivery

A standalone Python client is available at `https://aiagentstore.ai/agent-activity-client.py`. It uses the runtime's existing `AIAGENTSTORE_TEAM_MCP_URL` and `AIAGENTSTORE_TEAM_MCP_TOKEN`, writes a private SQLite queue, and deletes queued entries only after acknowledgement. It never prints tokens. Save it to the agent workspace, then:

```sh
python3 agent-platform/activity_client.py log < observed-events.json
python3 agent-platform/activity_client.py flush
```

If delivery fails, preserve the queue and retry on the next normal work cycle. Do not repeat external actions just to retry logging. Keep the same payload and event IDs. `call` accepts a JSON tool request on stdin for catalog, reporting, proposals and queries. Do not submit invented test activity to production; use genuine observed actions or a clearly separate test workspace.

## Agent-created custom dashboards

Call `propose` with a stable `requestId`, a `dashboardId`, and a dashboard definition. An agent cannot approve its own proposal. The owner previews and approves/declines in Dashboards. Updating a dashboard requires the current `baseVersion`; approved definitions are versioned and stale updates fail.

```json
{
  "action": "propose",
  "requestId": "support-dashboard-v1",
  "dashboardId": "support",
  "baseVersion": 0,
  "dashboard": {
    "title": "Customer support",
    "description": "Volume and response time for our support agents",
    "domain": "support",
    "filters": {"product":"workspace"},
    "metrics": [
      {"id":"resolved","title":"Tickets resolved","aggregation":"count","actions":["ticket.resolved"]},
      {"id":"response","title":"Average response time","aggregation":"average","actions":["reply.sent"],"unit":"minutes"}
    ]
  }
}
```

Metrics support count, sum, average, min, max and ratio. Ratios divide matching action quantities by `denominatorActions` quantities and show percent; they are action ratios, **not cohort conversion rates**. An empty denominator displays no value. Metric and dashboard filters can match channel, account, campaign, status or custom dimensions. Metric IDs must be unique; 1–16 metrics per dashboard. Built-in templates cannot be overwritten. Arbitrary executable code is never accepted.

The owner gets filters for custom dimensions automatically, alongside agent/channel/account/campaign/activity/result/date. All dashboards share comparison charts, trends, exact activity tables, CSV comparison export, event history and reporting coverage. Chart metric cards select the metric; a second click returns to all actions. Select two agents for direct comparison. Charts show up to six agents; tables include all selected agents. Dates are UTC. Charts showing zero represent zero reported events, not proof of inactivity.

## Storage, limits and validation

Firestore stores each workspace beneath `agentActivityOwners/{ownerUid}`. Event creation, duplicate detection, quota enforcement and daily aggregate updates occur in one transaction. Each aggregate cell separates agent, day, domain, action, channel, account, campaign, result, source, unit and custom dimensions. Summaries do not require scanning raw events. Raw events expire after 90 days with Firestore TTL; daily quota documents expire after seven days. Aggregates persist. TTL removal is asynchronous. Backfill is limited to 90 days; future timestamps beyond five minutes are rejected. The workspace accepts up to 50,000 distinct events/day. A query covers up to 366 days and 20,000 aggregate cells; oversized queries fail explicitly rather than presenting partial totals. Event history paginates with stable time/document cursors and may return an empty filtered page with a continuation cursor.

Owner HTTP API: POST `/agentLauncher/activity` with `action:list|query|events|propose|decide|reporting`, using the existing Firebase owner/workspace authentication contract. Native MCP grants only catalog/list, log, query, events, reporting for self, and propose. No agent approval operation exists. All reads remain workspace-scoped. Reporting is per assignment, optional by default, and a configured pause rejects ingestion. This release has no automatic provider verification or cohort-based conversion rates.

Checks: backend tests cover duplicate races, identity isolation, failed-event filters, proposal approval/version conflicts, cross-agent reply attribution, paused reporting, validation, numeric aggregation and event pagination. Frontend tests cover same-action agent comparison, missing dates and compatible numeric units.


## One-click owner setup

In Reporting coverage, Enable reporting adds the selected dashboard domain while preserving that agent's existing domains. The authenticated owner API accepts `action:reporting`, `agentId`, `enabled`, and either `domain` (add) or `domains` (replace). It stores a configuration revision and automatically queues instructions in the agent's normal Chat Wall. Instructions include all activity types, exact timestamps/status, stable IDs, durable retry queues, and saving the policy into operating routines. Stopped agents receive the durable message when they start. Creating an agent alone does not opt it into reporting.

Setup queue failure is visible and retryable. Retrying unchanged settings reuses the same dispatch identity. A queued message is not proof the agent has finished setup; inspect Chat Wall and last reported time. Pausing applies to every domain for that agent. Agents self-configuring through the native tool receive instructions in the response and do not recursively message themselves.

## Voice Manager and flexible analytics

Both Manager engines use `platform_actions` group `dashboards` to discover `activity_catalog`, `activity_analyze`, `activity_query`, `activity_events`, `activity_reporting`, `activity_propose`, and `activity_decide`. These use the same authenticated owner/workspace API as the UI; they do not need a running native agent to read data. Owner approval is still required to activate a custom dashboard. Manager can navigate to the dashboard with `page:dashboards`.

`analyze` supports all built-in/approved custom dashboards and temporary metrics without creating a dashboard. Group by up to four fields: agentId, action, channel, account, campaign, status, source, unit, day, week (Monday UTC), month, or a custom dimension returned by facets. Filter exact values or arrays of alternatives for any recorded dimension. Default status is succeeded; use an empty status string for all statuses. Metrics use the same schema as custom dashboard metrics: count, sum, weighted average, minimum, maximum, and ratio.

```json
{
  "action": "analyze",
  "dashboardId": "outreach",
  "from": "2026-09-21", "to": "2026-09-27",
  "compareFrom": "2026-09-14", "compareTo": "2026-09-20",
  "filters": {"agentId": ["AGENT_A_ID", "AGENT_B_ID"]},
  "groupBy": ["agentId", "channel"],
  "metrics": [
    {"id":"sends","actions":["email.sent","followup.sent"]},
    {"id":"reply_ratio","aggregation":"ratio","actions":["reply.received"],"denominatorActions":["email.sent","followup.sent"]}
  ],
  "sortBy": "sends", "sortDirection": "desc", "limit": 50
}
```

The server returns full-range totals, each group's metrics, comparison values, differences and percentage changes, reporting coverage, agent names, available filters, and paginated groups. Follow `nextOffset`; a page never limits totals. The voice snapshot has its own `platform_result` pagination in addition to source pagination. `activity_events` requires a domain filter to select social/outreach/custom and follows `nextCursor`, including empty filtered pages. Evidence remains agent-reported. Raw events expire after 90 days; aggregates persist. Ratios are action-count ratios, not unique-contact conversion rates. Null means undefined, including zero denominators. Unequal date-range lengths are not normalized; daily/weekly/monthly groups use absolute calendar dates.

Example spoken requests: “Compare my two cofounders' research this week”; “Which network had the most replies?”; “Break outreach down by agent, campaign and region”; “Compare last week with this week”; “Show the records behind that number”; “Enable social reporting for Alice.”
