DEV Community

kongkong
kongkong

Posted on

Build a Read-Only Analytics Tool Before Giving Your Agent Actions

The fastest way to make an analytics agent impressive is to let it answer broad natural-language questions. The fastest way to make it dangerous is to give the same path export, mutation, or deployment authority.

Ship one narrow read-only slice first.

type MetricRequest = {
  tenantId: string;
  metric: "daily_active_users" | "activation_rate";
  from: string;
  to: string;
  dimensions: Array<"plan" | "country">;
  requestId: string;
};

type MetricResponse = {
  definitionVersion: string;
  dataThrough: string;
  rows: Array<Record<string, string | number>>;
  sourceQueryId: string;
  warnings: string[];
};
Enter fullscreen mode Exit fullscreen mode

Validate dates, maximum range, dimensions, and metric names. Derive tenantId from authenticated server context rather than trusting the model. The query layer maps enums to pre-reviewed SQL or a semantic model; it never accepts model-generated SQL.

Make evidence travel end to end

The backend returns definition version, data freshness, query ID, and warnings. The tool adapter preserves them. The UI renders them beside the answer and offers a link to the source chart or query record.

Required UI states are loading, partial result, stale data, no data, forbidden, rate limited, cancelled, and evidence unavailable. “No rows” is different from “the warehouse failed.”

Cache only after authorization and canonicalization. Include tenant, metric, dimensions, date range, and definition version in the cache key. Do not cache user-level rows in shared infrastructure.

Test the seams

Write contract tests for unknown metrics, an unauthorized tenant, reversed dates, excessive range, unsupported dimensions, stale data, duplicate request ID, timeout, and a metric definition change during cache lifetime. Verify the browser cannot change tenant identity by editing tool arguments.

Only after the read path is observable and correctly authorized should you consider actions. Put writes in separate tools with separate credentials, previews, idempotency keys, and explicit approvals.

The public MonkeyCode repository describes model management, AI tasks, development environments, and team collaboration. It could be evaluated as a development workspace for this kind of integration, but this article does not claim an analytics or MCP integration with MonkeyCode.

Disclosure: I contribute to the MonkeyCode project. The architecture is tool-independent; product context comes from public documentation.

Read-only is not a toy milestone. It is where the team proves identity, evidence, freshness, and failure semantics before side effects make every mistake more expensive.

Top comments (0)