ChartnautDocs

Study authoring agent

The study builder's agent writes one study: which definitions it reads, what it collects per event, and what it publishes. Unlike the indicator and definition agents, it never applies an edit itself. Every change is a proposal you accept, and every run is a card you approve.

It does not write Forward Insight code. When the results look right, click Attach to chart on the run: the Forward Insight agent takes it from there.

How a change reaches you

  1. The agent calls propose_study_edit with the full study.js.

  2. Before you see anything, Chartnaut checks the proposal: it bundles and lints the study, checks that it exports scope(ctx) and that scope reads only what was known when the event fired, and dry-runs it on a preset market with its definitions computed at their pinned versions. A fault goes back to the agent to fix, up to three times.

  3. The Study edit proposal card appears. Show diff shows the change, Preview runs it, Accept saves it, and Reject sends it back with your reason.

  4. To run it, the agent proposes a run with propose_study_code_execution. Pick the datasets, check the Run window and any parameters, then click Run.

Accepting the card is also how you approve any new definition or indicator the study depends on. There is no separate approval.

In the chat box you can set how it talks: Guided (the default) keeps the code out of the way, Collaborative designs the measurements with you, and Technical is precise about the study's design.

Tools

Tool

Runs in

Does

get_study_state / read_study_files / list_study_versions

Server

The study's state, draft and versions

list_user_flows / read_flow_full / search_flows

Server

Finds definitions and reads their slug, latest version, payload fields and settings

search_indicators / resolve_dependency_contract

Server

Finds indicator dependencies and their exact accessor keys

propose_study_edit

Browser, asks you

The Study edit proposal card

propose_study_code_execution

Browser, asks you

The run card

execute_study_run / execute_study_runs

Server

Runs the study itself, only to recover when the normal run path failed

get_run_results

Server

Full payloads of a finished run's results

update_title

Server

Names the study, and renames it when its purpose changes

Dimension roles

A study that will become a Forward Insight splits its events by dimensions, and each dimension has a role. The agent declares roles explicitly so the attach wizard can use them.

Role

Means

In the tuple scope returns

Can index the Forward Insight

"scope" (the default)

Known when the event fired, such as the break direction

Required, on every path

Yes

"report"

Measured later, such as the next session's class

Never

No; only report tables

dimensions.declare({
  id: "direction",
  role: "scope",
  title: "Break direction",
  description: "Known on the clicked event.",
  values: ["up", "down"],
});
dimensions.declare({
  id: "next_regime",
  role: "report",
  title: "Next-day regime",
  description: "Measured from the following session.",
  values: ["rotational", "trending", "ranging"],
});

Two rules follow from the table:

  • scope(ctx) returns { direction } from what was known when the event fired, and onEvent(ctx, scope) measures what happened next. A read past the bar the event fired on throws inside scope, so the group a marker shows on Charts never depends on the future.

export function scope(ctx) {
  if (ctx.event.flow !== "orb") return null;
  return { direction: ctx.event.payload.direction };
}

export function onEvent(ctx, scope) {
  // measure the next session, collect it with its next_regime
}
  • Keep an outcome axis you still want in the report as role: "report". Deleting it to satisfy lint loses the report.

A pin-ready study also publishes at least one result indexed by its scope dimensions, with outcome shares or rates as value columns rather than extra index keys. A report table can be indexed more widely, for example by ["direction", "next_regime"].

What it checks before proposing

  • flows.declare and indicators.declare pin the latest version unless you asked for an older one.

  • ctx.collect is only in onEvent and ctx.publish only in onFinish.

  • Every result has a description, and heavy results have a small readout__* metric beside them.

  • No metric is published as NaN or Infinity, and a format: "percent" metric publishes a fraction between 0 and 1.

  • The sample size is the real count. It never inflates n.

Asking well

  • "Count bull_bar events from the bull alias and publish a count and a table."

  • "Collect the 10-bar forward return in ATR units; publish the mean and the median."

  • "Split by London direction as a scope dimension, and show the NY session class as a report dimension in a contingency table."

Requests it will not do: add a Forward Insight (use Attach to chart), emit events (studies read them), or pad a thin sample.