Skip to content

Research prompts

chronicle.research_prompts records the high-level research goal — the brief or question that anchors a subgraph of experiments — and links it to the experiments that pursue it.

A research prompt is a single immutable string (the goal), plus server-stamped provenance. You create it once, then attach it to one or more experiments; each experiment has at most one primary prompt. Created and returned records are flat dicts — {id, prompt, created_at, created_by} — with no SDK dataclass.

Reach it two ways: the stateless chronicle.research_prompts API (every call takes ids explicitly), or the per-experiment sugar exp.research_prompts that binds the experiment id for you. Prefer the sugar.

Create

create takes only the prompt text and returns the full created record. Prompts are immutable once created — there is no update.

rp = chronicle.research_prompts.create(
    "Does Fourier feature conditioning improve convergence on stiff PDEs?"
)
print(rp["id"], rp["prompt"], rp["created_at"], rp["created_by"])

The create endpoint does not link to experiments. Pass experiment_ids to attach the new prompt to those experiments in follow-up calls (none of them primary):

rp = chronicle.research_prompts.create("...", experiment_ids=["exp_7Qk", "exp_9Lm"])

Attach

attach associates an existing prompt with an experiment. Set primary=True to make it the experiment's primary prompt. Requires Write on the experiment; returns {experiment_id, research_prompt_id, is_primary}.

chronicle.research_prompts.attach("exp_7Qk", rp["id"], primary=True)

# Sugar — the experiment id is bound.
exp = chronicle.experiment("exp_7Qk")
exp.research_prompts.attach(rp["id"], primary=True)

The bound shim also offers a one-call create that creates the prompt and attaches it to this experiment:

rp = exp.research_prompts.create("Investigate spectral bias under mixed precision", primary=True)

List for an experiment

Each list entry is {research_prompt: {...}, is_primary: bool} — at most one has is_primary: true. Requires Read on the experiment.

for entry in exp.research_prompts.list():          # sugar
    star = "*" if entry["is_primary"] else " "
    print(star, entry["research_prompt"]["prompt"])

prompts = chronicle.research_prompts.list_for_experiment("exp_7Qk")   # stateless equivalent

Fetch one by id

get returns {id, prompt, created_at, created_by} and raises NotFoundError if the prompt doesn't exist.

rp = chronicle.research_prompts.get(rp_id)

Methods at a glance

Stateless Bound (exp.research_prompts) Returns
create(prompt, *, experiment_ids=None) create(prompt, *, primary=False) created record {id, prompt, created_at, created_by}
attach(experiment_id, research_prompt_id, *, primary=False) attach(research_prompt_id, *, primary=False) {experiment_id, research_prompt_id, is_primary}
list_for_experiment(experiment_id) list() [{research_prompt, is_primary}]
get(research_prompt_id) {id, prompt, created_at, created_by}

The two create forms differ: the bound one attaches to its experiment (honoring primary); the stateless experiment_ids form attaches non-primary. See the client reference for authoritative signatures, and reports for the same experiment-scoped sugar pattern.