Skip to content

[stats] Configure stats from MCP and from the agent itself — one validator, no privileged path #312

Description

@serge-ivo

The "configurable by MCP or by the agent itself on the user's request" half of #310.

Three writers, one schema, one validator

Who Path Scope
Creator agents.config.statsSchema the default every subscriber inherits
Subscriber agent_instances.config.stats their own override, merged per card
The agent set_stats_card tool writes the subscriber override, same as a human would

All three go through the same sanitizer and the same closed source vocabulary from #310. That
is the whole safety story: there is no privileged path that skips validation, so "the agent
configured it" and "the user configured it" cannot diverge in what they are allowed to express.

MCP tools — mirror the settings-schema pair that already exists

get_agent_settings_schema / set_agent_settings_schema are the precedent; follow it exactly:

  • get_agent_stats_schema / set_agent_stats_schema — creator-side, on the agent.
  • get_instance_stats / set_instance_stats — subscriber-side, on the instance.

Both mutating tools are write-scoped and go through the MCP write gate, like every other
mutation (call_instance_tool is already gated wholesale as write).

The agent's own tools

  • get_stats — read the resolved cards and their current values. This is what makes the
    feature conversational: "how many leads did I find this week?" should be answerable from the same
    numbers the tab shows, not recomputed by the model from a collection dump.
  • set_stats_card — add / edit / remove one card. Patch semantics, null clears, rejections
    reported rather than swallowed (the set_behaviour shape from Agent Behaviour: get_behaviour / set_behaviour, with guardrails excluded from self-writes #224 — a tool that half-applies a
    patch and returns success teaches the model it changed something it did not).

Both base-tier, for the same reason get_behaviour / set_behaviour are: any agent can be asked
"track this for me", and an agent with no proper place to put the answer invents one. That is
exactly how preference:response_style ended up in memory (#226) and how a Repo Coder invented a
pipeline named "coding".

What the agent may NOT do

  • It cannot add a source. The vocabulary is code, reviewed, owner-scoped ([stats] Per-agent Stats tab — declarative card schema over a closed, owner-scoped source vocabulary #310).
  • It cannot change scope, only view — the schema says what to show, never whose data.
  • It cannot write the creator schema. A subscriber's agent editing the agent template would
    change what every other subscriber gets; set_stats_card writes the instance override only. This
    is the same boundary patchBehaviour already holds ("a subscriber changing their mind must not
    edit the agent every other subscriber gets").

Prompt awareness

If an agent has stats cards, agent-think should say so — briefly, and derived from the resolved
schema, not hardcoded prose. An agent that can answer "how many leads this week" but is never told
it has the tool will not use it. Same failure as #254, where the prompt asserted a capability the
tool set contradicted; derive the sentence from the resolved tools, do not write it.

Verification

  • A card set by the agent is byte-identical to the same card set by a human through the API.
  • set_stats_card naming an unknown source is refused, by name, and other cards in the patch still
    apply.
  • The agent cannot write agents.config.statsSchema through any tool.
  • get_stats returns the same numbers the Stats tab shows for the same window.
  • An agent with no cards is not told it has any.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions