Client reference¶
Top-level¶
methodic.Chronicle ¶
Chronicle(
server_url: str,
api_key: str,
timeout: int = 30,
max_upload_workers: int = 2,
organization_id: str | None = None,
organization_slug: str | None = None,
)
Client for the Chronicle REST API.
Construct once with the server URL + API key, then call into namespaces:
chronicle = Chronicle(server_url="https://api.methodiclabs.ai", api_key="sk_...")
Or resolve credentials from the environment / a config file (see
from_env and from_file) — the form the Chronicle skills use:
chronicle = Chronicle.from_env() # CHRONICLE_SERVER_URL + CHRONICLE_API_KEY
Then call into namespaces:
# Researcher
exp = chronicle.experiments.create(hypothesis_summary="...", config_yaml="...")
exp.commit().variations.create(config_yaml="...")
# Worker
run = chronicle.run(experiment_id, variation, run_idx)
run.start().heartbeat()
run.upload_asset(asset_type="research_report", content={"summary": "..."})
run.succeed()
Use as a context manager to guarantee the executor and HTTP session are closed.
Construct via :meth:from_env (reads CHRONICLE_SERVER_URL +
CHRONICLE_API_KEY) or directly with server_url + api_key.
Organization scope resolves per call, with an optional client default:
pass organization_id on the call itself (e.g.
experiments.create(..., organization_id=...)), or set a default once —
organization_id: in ~/.methodic/config.yaml or
$CHRONICLE_ORGANIZATION_ID — and omit it. With a default configured,
pass methodic.PERSONAL to force a personal-scope call. There is no
per-request header; resolution happens in the SDK call.
organization_id
property
¶
The default organization for calls that take an organization_id
and were not given one (None = personal scope).
When configured by slug (organization_slug / the
CHRONICLE_ORGANIZATION_SLUG env / the organization_slug: config
key), the slug is resolved to its principal id via /v1/me/scopes on
first read and cached for the client's lifetime; a slug matching no
organization you belong to raises ChronicleConfigError.
experiment ¶
Get a handle for an existing experiment by id (lazy — no fetch until accessed).
from_env
classmethod
¶
Construct a client from the ambient environment.
Resolution order, highest precedence first:
- explicit keyword arguments —
server_url,api_key,timeout,max_upload_workers,organization_id - environment variables —
CHRONICLE_SERVER_URL,CHRONICLE_API_KEY,CHRONICLE_TIMEOUT,CHRONICLE_MAX_UPLOAD_WORKERS,CHRONICLE_ORGANIZATION_ID - YAML files under
~/.methodic—config.yaml(non-secret settings) thencredentials.yaml(the API key); or a single file pointed to byCHRONICLE_CONFIG - built-in defaults (
server_url→https://api.methodiclabs.ai)
api_key has no default; raises ChronicleConfigError if it cannot
be resolved from any source, or if a setting is malformed.
This is the entry point the Chronicle skills call, so setting either the environment variables or the config file is enough to run them.
from_file
classmethod
¶
from_file(
config: str | Path | None = None,
credentials: str | Path | None = None,
**overrides: Any,
) -> Chronicle
Construct a client from explicit YAML files.
Mirrors the ~/.methodic split so the same files work with either
entry point: a non-secret config file and/or a credentials file
holding the API key. Each is a flat mapping::
# config.yaml
server_url: https://api.methodiclabs.ai
timeout: 30 # optional
# credentials.yaml
api_key: sk_user_...
Either may carry any subset (a single combined file can be passed as
config); credentials wins over config on overlap, and
explicit keyword arguments win over both. Unlike from_env, this does
not consult environment variables. Raises ChronicleConfigError if a
named file is missing or malformed, or if no api_key is present.
run ¶
Construct a Run resource handle bound to one (experiment, variation, run).
variation ¶
Get a handle for an existing variation by (experiment_id, variation).
Resource handles¶
methodic.Experiment ¶
Experiment(
chronicle: Chronicle,
experiment_id: str,
*,
_detail: ExperimentDetail | None = None,
_create_response: CreateExperimentResponse
| None = None,
)
Handle for one experiment.
Mutators (commit, conclude, retract) return self so callers can
chain (exp.commit().variations.create(...)). Cached detail is dropped
after each mutation; the next attribute access re-fetches transparently.
delete ¶
Hard-delete this open experiment (see
:meth:ExperimentsAPI.delete). The handle is dead after this
returns — the experiment row and its cascade are gone.
distill ¶
distill(
*,
scope: str,
variation_id: int | None = None,
corpus_filter: dict[str, Any] | None = None,
write_research_report: bool = True,
reason: str | None = None,
) -> dict[str, Any]
Trigger a distillation agent for this experiment (M9 §17).
fork ¶
fork(
*,
hypothesis_summary: str,
rationale: str | None = None,
config_yaml: str | None = None,
slug: str | None = None,
allow_retracted_parent: bool = False,
) -> "Experiment"
Fork this experiment. Proxies to ExperimentsAPI.fork.
get_agent_config ¶
Read this experiment's agent_config block (M11).
git_status ¶
Lightweight current git-integration state for this experiment.
mint_git_token ¶
Mint a 1-hour install token scoped to this experiment's repo.
move ¶
move(
*,
organization_id: str,
team_id: str | None = None,
visibility: str | None = None,
) -> Experiment
Transfer this experiment into an org (see
:meth:ExperimentsAPI.move). Drops cached detail and returns
self so calls can chain.
set_agent_config ¶
Replace this experiment's agent_config block.
set_continuous_exploration ¶
set_continuous_exploration(
*,
enabled: bool,
trigger_scope: str = "variation",
cooldown_minutes: int = 0,
) -> dict[str, Any]
Configure the M11 continuous-exploration loop on this
experiment. Convenience wrapper that read-modify-writes
agent_config.continuous_exploration.
set_report_settings ¶
Replace experiment.report_settings. Frozen at commit (server
returns 409 once committed). settings shape matches the
ReportSettings server type:
{
"hypothesis": {"mode": "freeform", "freeform_prompt": "..."},
"takeaways": {"mode": "template", "template_asset_id": "...", "per_variation": true},
"research": {...}
}
Returns self for chaining. Drops cached _detail so the next
access re-fetches the updated row.
wait_for_repo ¶
Poll until this experiment's repo is ready (or failed/timeout).
methodic.Variation ¶
Variation(
chronicle: Chronicle,
experiment_id: str,
variation: int,
*,
_data: Variation | None = None,
)
Handle for one variation. Holds (experiment_id, variation) and lazy-loaded data.
data
property
¶
Server-side variation record. Auto-fetched on first access; refetched after mutations.
list_outputs ¶
List this variation's output assets across all runs (raw dicts), newest-first — produced checkpoints, snapshots, and reports.
set_git_ref ¶
Bind a branch to this (open) variation. Returns self for chaining.
unlink_input ¶
Unlink an input asset from this (open) variation. Returns self for chaining.
update ¶
update(
*,
hypothesis: str | None = None,
expected_outcome: str | None = None,
description: str | None = None,
name: str | None = None,
) -> Variation
Edit this (open) variation's mutable metadata. Returns self for chaining.
methodic.Run ¶
Handle for a specific (experiment_id, variation, run) run.
Mutators return self so worker code can chain (run.start().heartbeat()).
Asset-upload helpers auto-populate output_of from the bound triple.
create_asset_presigned ¶
create_asset_presigned(
asset_type: str,
components: list[str],
name: str | None = None,
content_type: str = "application/octet-stream",
) -> AssetUploadInfo
Register a new asset for component upload via presigned URLs.
latest_output ¶
latest_output(
asset_type: str | None = None,
*,
across_runs: bool = True,
ready_only: bool = True,
) -> dict[str, Any] | None
Return the most recent matching output asset, or None — the
resume-discovery helper.
Filters by asset_type (e.g. "checkpoint") and, by default, to
state == "ready" (finalized + immutable). Searches across all runs of
the variation by default. Pair with :meth:download_asset::
ckpt = run.latest_output("checkpoint")
if ckpt:
run.download_asset(ckpt["id"], Path("./resume"))
list_outputs ¶
List this run's output assets (newest-first). With
across_runs=True, list outputs across all runs of the variation
— the scope to use when resuming, since the checkpoint to resume from
was produced by an earlier run.
register_and_upload_async ¶
register_and_upload_async(
local_dir: Path,
asset_type: str,
upload_tracker: UploadTracker,
content_type: str = "application/octet-stream",
) -> str
Register every file in a directory, then upload + finalize on a background thread.
upload_asset ¶
upload_asset(
asset_type: str,
content: Any,
name: str | None = None,
content_type: str = "application/json",
asset_config: dict[str, Any] | None = None,
) -> dict[str, Any]
Upload a small inline asset (auto-finalized). Linked to this run as output.
upload_directory_async ¶
upload_directory_async(
local_dir: Path,
asset_type: str,
content_type: str = "application/octet-stream",
upload_tracker: UploadTracker | None = None,
) -> None
Upload every file in a directory on a background thread.
With upload_tracker, uses the register-then-upload flow for crash
recovery. Without, a thinner path that uploads and finalizes inline.
Namespaces¶
methodic.ExperimentsAPI ¶
Experiments namespace. Stateless; every method takes the experiment id explicitly.
conclude ¶
Conclude an experiment: lock all outputs, no new variations. Terminal.
Not idempotent — re-concluding a concluded experiment raises (409
already_concluded). Gates on a satisfying experiment-level
takeaways_report; if none exists the server schedules a
distillation and the 409 body carries distillation_job_id to poll,
then re-issue conclude.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
experiment_id
|
str
|
Target experiment. |
required |
on_exist_action
|
str | None
|
|
None
|
create ¶
create(
*,
hypothesis_summary: str,
config_yaml: str,
rationale: str | None = None,
description: str | None = None,
accelerate_config_yaml: str | None = None,
launch_config: dict[str, Any] | None = None,
parent_experiment_ids: list[str] | None = None,
allow_retracted_parent: bool = False,
organization_id: str | None = None,
team_id: str | None = None,
visibility: str | None = None,
) -> Experiment
Create a new experiment. Returns a handle with the create-response cached.
Organization scope: pass organization_id (and/or team_id) to
create the experiment under that org/team. Omitting it falls back to
the client's configured default org (the organization_id setting —
see Chronicle); with a default configured, pass methodic.PERSONAL
for a personal experiment owned by the calling key's user.
visibility controls who can read the experiment and its reports:
"private" (creator + org admins only), "organization" /
"team" (the owning org or team gets read + discuss, and its reports
become discoverable in search), or "public" (anyone, read-only).
Omit it for the scope-derived default — org/team-wide in an org
context, private in personal space.
delete ¶
Hard-delete an open (uncommitted) experiment and everything it owns (variations, runs, asset/research-prompt links, ACLs, auto-roles, and best-effort the GitHub repo + search doc). Returns the server's removal summary.
Refused with ConflictError (409) once the experiment is committed
or concluded — retract it instead — or if another experiment was
derived from it (remove the descendants first). Requires the
Delete action. The underlying asset rows survive (they may be
shared across experiments); only this experiment's link rows go.
distill ¶
distill(
experiment_id: str,
*,
scope: str,
variation_id: int | None = None,
corpus_filter: dict[str, Any] | None = None,
write_research_report: bool = True,
reason: str | None = None,
) -> dict[str, Any]
Trigger a distillation agent for the experiment (M9 §17).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
experiment_id
|
str
|
Target experiment. |
required |
scope
|
str
|
|
required |
variation_id
|
int | None
|
Required when |
None
|
corpus_filter
|
dict[str, Any] | None
|
Required when |
None
|
write_research_report
|
bool
|
Whether to also write a
|
True
|
reason
|
str | None
|
Free-form audit string. |
None
|
Returns the 202 body: {distillation_job_id, scope,
expected_outputs, tartarus_instance_id}. Distillation runs
async inside tartarus-d; poll
GET /experiments/{id}/agents to watch progress.
fork ¶
fork(
experiment_id: str,
*,
hypothesis_summary: str,
rationale: str | None = None,
config_yaml: str | None = None,
slug: str | None = None,
allow_retracted_parent: bool = False,
) -> Experiment
Fork an experiment: create a new experiment whose repo mirrors the source's full git history, with a lineage edge to the source. Returns a handle to the new (forked) experiment.
get_agent_config ¶
Read the experiment's agent_config JSON block (M11).
Returns {} for experiments that never had a block set.
Shape per runes/chronicle/designs/agent-flows.md §13:
distillation (default-on auto-trigger + auto-on-conclude
knobs) and continuous_exploration (opt-in synthesis
wake-up loop).
git_status ¶
Current git-integration state for the experiment.
Returns lightweight status info — state (pending/ready/failed/archived),
repo_url (when ready), failure_reason (when failed). Cheap to poll;
UI calls this every couple seconds while state is pending.
iter ¶
iter(
*,
status: str | None = None,
created_by: str | None = None,
page_size: int | None = None,
) -> Iterator[ExperimentSummary]
Yield every experiment matching the filters, paging server-side as needed.
list ¶
list(
*,
status: str | None = None,
created_by: str | None = None,
page_size: int | None = None,
page_token: str | None = None,
) -> ExperimentListPage
One page of experiments matching the filters.
The server paginates on ?limit + ?before=<created_at>_<id> and
returns a bare array (no envelope token); page_size / page_token
are the SDK's stable names for those. The next cursor is derived from
the last row when the page comes back full — a short page is the end.
Use :meth:iter to walk every page.
mint_git_token ¶
Mint a 1-hour install token scoped to this experiment's repo.
The returned token has Administration permission stripped — pushes
to agent/* branches will be rejected by branch protection. Use it
to clone the repo and push to user/... branches you create.
Raises ServerError(503) if the server has no GitHub App configured;
ConflictError(409) if the experiment's repo isn't ready yet.
move ¶
move(
experiment_id: str,
*,
organization_id: str,
team_id: str | None = None,
visibility: str | None = None,
) -> dict[str, Any]
Transfer a personal experiment into an organization.
Personal → org only: the experiment's owner becomes
organization_id (and team_id if given), the org's admins gain
read + administer, and visibility sets who else can read it —
"private" (creator + org admins), "organization" / "team"
(org/team members get read + discuss; the default in an org context),
or "public" (anyone). The original creator keeps their access; the
move only adds org reach (owner_subject is unchanged).
Raises ConflictError (409) if the experiment is already owned by an
org, or if its slug collides with an existing experiment in the target
org (rename it first via PUT /experiments/{id}). Requires
Administer on the experiment and membership of the target org.
set_agent_config ¶
Replace the experiment's agent_config block.
Validates the continuous_exploration sub-block strictly
(400 with kind: "invalid_continuous_exploration" on
malformed shape); other sub-blocks pass through. Pass {}
to clear all knobs back to defaults.
set_continuous_exploration ¶
set_continuous_exploration(
experiment_id: str,
*,
enabled: bool,
trigger_scope: str = "variation",
cooldown_minutes: int = 0,
) -> dict[str, Any]
Convenience wrapper around :meth:set_agent_config for
the M11 continuous_exploration block.
Merges the new block into the existing agent_config (read
first, then PUT) so other knobs (distillation defaults,
steering caps, etc.) are preserved.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
experiment_id
|
str
|
Target experiment. |
required |
enabled
|
bool
|
Whether the closed-loop wake-up fires on distillation completion. |
required |
trigger_scope
|
str
|
|
'variation'
|
cooldown_minutes
|
int
|
0 .. 1440. |
0
|
wait_for_repo ¶
wait_for_repo(
experiment_id: str,
*,
timeout: float = 300.0,
poll_interval: float = 2.0,
) -> GitStatus
Poll git_status until the repo is ready or failed, or timeout.
methodic.VariationsAPI ¶
Variations namespace. Keys every operation on (experiment_id, variation).
commit ¶
commit(
experiment_id: str,
variation: int,
*,
commit_without_hypothesis: bool = False,
) -> dict[str, Any]
Commit (lock) a variation. Refused (409 missing_variation_hypothesis)
when the variation has no recorded hypothesis unless
commit_without_hypothesis=True — a deliberate, audited choice to
commit without pre-registration.
create ¶
create(
experiment_id: str,
*,
config_yaml: str,
accelerate_config_yaml: str | None = None,
launch_config: dict[str, Any] | None = None,
description: str | None = None,
input_asset_ids: list[str] | None = None,
git_ref: str | None = None,
name: str | None = None,
hypothesis: str | None = None,
expected_outcome: str | None = None,
) -> Variation
Create a new variation under experiment_id. Returns a Variation handle.
hypothesis records the falsifiable hypothesis this variation
validates (tied to the eval metric) — the variation's pre-registration,
the analog of an experiment's hypothesis. expected_outcome is the
predicted result vs. baseline. Both can also be set/refined after
creation via :meth:update while the variation is open. A variation
with no hypothesis can only be committed via the explicit
commit_without_hypothesis override.
git_ref optionally associates the variation with a branch on the
experiment's GitHub repo. Server captures the branch name now;
SHA resolution + the branch-rename-to-agent/... flow happens at
variation commit (Phase 3). Pre-Phase-3, registering with git_ref
is informational only.
list_inputs ¶
List the variation's input assets (each a dict with id,
asset_type, name, …). Use to find a linked code_artifact —
e.g. a bundle to clean up after rebinding the variation to git.
list_outputs ¶
List the variation's output assets across all its runs (each a dict
with id, asset_type, name, state, created_at, …),
newest-first. Use to find produced checkpoints, snapshots, and reports —
e.g. the latest ready checkpoint to resume from.
set_git_ref ¶
Bind a branch to an open variation — records the variation→branch mapping without pinning a SHA (the SHA locks at commit).
Used by the create-first fork flow: create the variation, name the
branch variation/<id>, push it, then bind it here so a tartarus
agent (or the commit-time rename) knows which branch belongs to the
variation. The server rejects the protected agent/* namespace and
returns 409 if the variation is already committed.
unlink_input ¶
Remove an input-asset link from an open variation.
Unlinks the asset from the variation's inputs without deleting the asset
itself — hard-delete the now-orphaned asset separately via
chronicle.assets.delete. Refused with 409 once the variation is
committed (inputs freeze on commit). Used to drop a stale
code_artifact — e.g. a bundle that a later git-ref binding
superseded — while the variation is still open.
update ¶
update(
experiment_id: str,
variation: int,
*,
hypothesis: str | None = None,
expected_outcome: str | None = None,
description: str | None = None,
name: str | None = None,
) -> VariationData
Edit an open variation's mutable metadata. Omitted fields are
left untouched; pass "" to clear one. Raises (409) once the
variation is committed. Primary use: record or refine the
pre-registered hypothesis before commit.
methodic.RunsAPI ¶
Run-lifecycle namespace. Stateless across calls; takes the run triple as args.
fail ¶
Mark a run failed. reason is crash (worker error) or abandoned (cancel).
list_outputs ¶
List the output assets produced by a single run (newest-first).
list_variation_outputs ¶
List output assets produced across all runs of a variation (newest-first). The resume-discovery scope: a fresh run finds the prior run's checkpoint here.
start ¶
start(
experiment_id: str,
variation: int,
run: int,
*,
wandb_run_id: str | None = None,
wandb_entity: str | None = None,
wandb_project: str | None = None,
wandb_dashboard_url: str | None = None,
) -> None
Mark the run started. Optionally link its W&B run by passing the full
triple (wandb_run_id + wandb_entity + wandb_project; project falls
back server-side to the experiment's wandb_project). The link is the
(exp,var,run) → W&B run pointer distillation reads — agent-side with
its own key, or via the backend wandb_fetch_* broker.
methodic.AssetsAPI ¶
AssetsAPI(
transport: Transport,
*,
chronicle: Chronicle | None = None,
default_organization_id: str | None = None,
)
Asset operations.
Output-of linking (which experiment/variation/run produced this asset) is
passed explicitly by callers — Run populates it from its bound context,
while researcher-level uploads pass it directly or omit it for shared assets.
approve ¶
Clear review_required from an asset's pending_reasons.
Auto-finalizes the asset if that was the last reason (state → ready).
Idempotent on already-terminal assets. See design.md § Pending reasons.
Requires Write permission on the asset.
bulk_approve ¶
bulk_approve(
asset_ids: list[str] | None = None,
*,
all_in_scope: bool = False,
) -> BulkApproveResponse
Approve review-gated reports in a batch — the attention feed's "approve selected" / "approve all" action.
Exactly one mode (a ValueError is raised before any request otherwise):
- pass
asset_idsto approve the listed assets ("approve selected"); - pass
all_in_scope=Trueto approve every pendingreview_requiredasset the caller can act on in scope ("approve all N").
Partial success is normal: the call returns HTTP 200 with a per-asset
result list, and a 404 / permission denial / validation failure on one
asset surfaces as an "error" row rather than aborting the batch.
Each asset's Write permission is re-checked server-side, so an
all_in_scope candidate you can read but not write fails its own row.
Returns a :class:~methodic.types.BulkApproveResponse (results +
approved / failed counts).
create_inline ¶
create_inline(
*,
asset_type: str,
content: Any,
name: str | None = None,
content_type: str = "application/json",
output_of: dict[str, Any] | None = None,
asset_config: dict[str, Any] | None = None,
pending_reasons: list[str] | None = None,
organization_id: str | None = None,
team_id: str | None = None,
visibility: str | None = None,
) -> dict[str, Any]
Upload a small inline asset. Chronicle auto-finalizes unless
pending_reasons is non-empty — see design.md § Pending reasons.
Valid reasons: upload_in_progress (not on inline content),
compile_pending, review_required.
Pass organization_id (and/or team_id) to create the dataset
under an org you belong to, and visibility ("private" |
"organization" / "team" | "public") to set who else can read
it — same model as experiments.create. Omitting organization_id
falls back to the client's configured default org (if any); pass
methodic.PERSONAL to force a personal, private dataset.
create_with_presigned ¶
create_with_presigned(
*,
asset_type: str,
components: list[str],
name: str | None = None,
content_type: str = "application/octet-stream",
output_of: dict[str, Any] | None = None,
asset_config: dict[str, Any] | None = None,
pending_reasons: list[str] | None = None,
organization_id: str | None = None,
team_id: str | None = None,
visibility: str | None = None,
) -> AssetUploadInfo
Register a new asset and get presigned PUT URLs for each component.
Accepts an optional asset_config (stored on the asset — datasets put
their provenance record here) and a pending_reasons list (see
create_inline). organization_id / team_id / visibility
set the dataset's org context + visibility (see create_inline);
organization_id falls back to the client's configured default org.
delete ¶
Hard-delete an asset that is not linked to any experiment — no experiment/variation input links and no output links reference it. The cleanup path for orphans (over-uploaded datasets, abandoned pending uploads). Removes the row, its ACLs, inline content, storage bytes, and search document. Returns the server's removal summary. Irreversible.
Refused with ConflictError (409, kind: "asset_linked",
per-table counts in links) while the asset is linked anywhere —
a linked asset is part of an experiment's record; take it out of
use with :meth:deprecate/:meth:invalidate instead. Requires the
Delete action on the asset.
deprecate ¶
Soft-warn on an asset: it stays usable as an input, but the
deprecation (with reason) is surfaced as a warning wherever it
is linked. The right call for "superseded, but existing results
stand". Returns the updated asset.
download ¶
Download all components of an asset to a local directory.
finalize ¶
Mark a presigned-upload asset as ready (immutable) once all components are up.
get ¶
Fetch asset metadata. With include_presigned=True, includes read URLs.
grant_access ¶
Grant a principal (a user sub, team id, org id, or everyone) an
action on a dataset/asset. action defaults to read; others:
write, delete, administer. Idempotent. Requires
Administer on the asset (its creator has it).
invalidate ¶
Hard-block an asset: it can no longer be linked as an input
without allow_invalid_assets. The row, links, and provenance
survive (unlike :meth:delete) — the right call for "wrong data,
do not build on this" when the asset is part of an experiment's
record. Returns the updated asset.
list_access ¶
List the access-control entries on a dataset/asset — who can
read/write it. Requires Read on the asset. Returns the server's
object-aces payload.
move ¶
move(
asset_id: str,
*,
organization_id: str,
team_id: str | None = None,
visibility: str | None = None,
) -> dict[str, Any]
Transfer a dataset/asset into an organization — the asset analog of
experiments.move. Sets its owning org/team so it lists under the org
(GET /assets?owner=…) and bills to it; visibility ("private"
| "organization" / "team" | "public", default org-wide) sets
who else can read it. Requires Administer on the asset and
membership of the target org (resolve the id via
chronicle.me.scopes()). created_by is unchanged.
presign ¶
presign(
asset_id: str,
*,
operation: str = "read",
components: list[str] | None = None,
) -> dict[str, Any]
Request presigned URLs for an asset's components.
reject ¶
Reject a review-gated asset — clears review_required AND
transitions pending → abandoned, recording rejected_at and
rejection_reason. Requires Write on the asset; reason is
a required free-text explanation surfaced in audit + UI.
revoke_access ¶
Revoke a principal's (principal, action) grant on a dataset.
Idempotent — the response removed is False if the grant didn't
exist. Requires Administer on the asset.
set_visibility ¶
Set an asset's visibility — its broadcast read grant — independent of
any experiment it's linked to. visibility is "private" | "org"
(a.k.a. "organization" / "team") | "public".
Use this to share a single report/dataset more widely — e.g. make one
report "public" — without exposing the whole experiment. "private"
removes the broadcast grant; per-person shares from :meth:grant_access
and experiment-inherited access are left untouched (visibility controls
only the single broadcast grant). Unlike :meth:move, this does not
change the asset's owning org. Requires Administer on the asset (its
creator has it; an experiment's admins have it on the experiment's
reports). Returns the asset.
share_with_scope ¶
Share a dataset with a whole team or organization: grant the scope
(a team/org id — see chronicle.me.scopes()) read (default) on
the asset so its members reach it. A thin convenience over
:meth:grant_access; requires Administer on the asset and that you
belong to the scope.
upload_component ¶
PUT one component to its presigned URL.
methodic.SearchAPI ¶
Vertex-backed search across research docs, experiment metadata, and arxiv assets.
history ¶
history(
query: str,
*,
experiment_context: list[str] | None = None,
created_by: str | None = None,
created_after: str | None = None,
created_before: str | None = None,
asset_types: list[str] | None = None,
page_size: int | None = None,
page_token: str | None = None,
) -> SearchResponse
Search Chronicle's INTERNAL corpus — your experiment history and internal research documents (hypothesis/takeaways/research reports, experiment metadata).
This is a semantic alias for :meth:query with the common
narrowing knobs (author, time window, asset type) lifted into
keyword args and assembled into a SearchFilters. It hits the same
POST /search endpoint and is RBAC- and storage-prefix-scoped
server-side.
NOTE: this does NOT search external literature. arxiv / paper search is served by a SEPARATE external MCP, not by this method or by Chronicle's search API.
asset_types defaults to None — Chronicle already excludes session
assets server-side, so the unfiltered corpus is the right default.
Pass a list to narrow to specific types (e.g.
["research_report"]).
iter ¶
iter(
query: str,
*,
filters: SearchFilters | dict[str, Any] | None = None,
experiment_context: list[str] | None = None,
scope: SearchScope | dict[str, Any] | None = None,
page_size: int | None = None,
) -> Iterator[SearchResult]
Yield every search hit, paging server-side as needed.
query ¶
query(
query: str,
*,
filters: SearchFilters | dict[str, Any] | None = None,
experiment_context: list[str] | None = None,
scope: SearchScope | dict[str, Any] | None = None,
page_size: int | None = None,
page_token: str | None = None,
) -> SearchResponse
Run a single search request. Returns one page; use iter to walk pages.
scope is a HARD filter that restricts results to the union of the
named collections + experiments (and member experiments' outputs),
distinct from experiment_context which only boosts. Pass a
:class:~methodic.SearchScope or a raw {collections, experiments}
dict; an empty scope paired with experiment_context hard-scopes to
that context. See collections.md §"Search integration".
Response types¶
methodic.ExperimentData
dataclass
¶
ExperimentData(
id: str,
owner_subject: str,
hypothesis_summary: str,
created_at: str,
created_by: str,
state: str,
rationale: str | None = None,
description: str | None = None,
committed_at: str | None = None,
concluded_at: str | None = None,
retracted_at: str | None = None,
retraction_reason: str | None = None,
git_repo_state: str = "pending",
git_repo_url: str | None = None,
git_repo_failure_reason: str | None = None,
)
Mirror of the server's Experiment struct.
git_repo_state defaults to "pending" so older server payloads (which
may not include the field yet) deserialize cleanly.
methodic.ExperimentDetail
dataclass
¶
ExperimentDetail(
experiment: Experiment,
parent_ids: list[str],
variations: list[VariationSummary],
)
GET /experiments/{id} response: experiment + parents + variation summaries.
methodic.ExperimentSummary
dataclass
¶
ExperimentSummary(
id: str,
hypothesis_summary: str,
variation_count: int,
created_at: str,
created_by: str,
state: str,
status: str | None = None,
committed_at: str | None = None,
concluded_at: str | None = None,
retracted_at: str | None = None,
)
One row in the experiments list.
methodic.ExperimentListPage
dataclass
¶
One page of experiments.list results plus a cursor for the next page.
The current server returns a flat array; we normalize that into a
single-page response with next_page_token=None. When the server
grows pagination, the same dataclass keeps working.
methodic.VariationData
dataclass
¶
VariationData(
experiment_id: str,
variation: int,
config_json: dict[str, Any],
config_yaml: str,
created_at: str,
created_by: str,
state: str,
accelerate_config_json: dict[str, Any] | None = None,
accelerate_config_yaml: str | None = None,
launch_config: dict[str, Any] | None = None,
description: str | None = None,
committed_at: str | None = None,
retracted_at: str | None = None,
retraction_reason: str | None = None,
git_ref: str | None = None,
git_sha: str | None = None,
name: str | None = None,
hypothesis: str | None = None,
expected_outcome: str | None = None,
)
Mirror of the server's Variation struct.
config_json, accelerate_config_json, and launch_config arrive as
arbitrary JSON — kept as dict[str, Any] since the schema is open.
methodic.VariationSummary
dataclass
¶
VariationSummary(
variation: int,
created_at: str,
run_count: int,
state: str,
description: str | None = None,
latest_status: str | None = None,
committed_at: str | None = None,
retracted_at: str | None = None,
name: str | None = None,
hypothesis: str | None = None,
)
One variation as it appears in ExperimentDetail.variations.
methodic.LineageResponse
dataclass
¶
methodic.UpstreamRetraction
dataclass
¶
UpstreamRetraction(
experiment_id: str,
retracted_at: str,
reason: str,
depth: int,
variation: int | None = None,
document_asset_id: str | None = None,
chain: list[str] | None = None,
)
methodic.UpstreamRetractionsResponse
dataclass
¶
methodic.CreateExperimentResponse
dataclass
¶
POST /experiments response: the new experiment plus the always-created variation 0 / run 0.
methodic.SearchResult
dataclass
¶
SearchResult(
document_id: str,
source_type: str,
relevance_score: float,
lineage_boost: bool,
asset_type: str | None = None,
title: str | None = None,
snippet: str | None = None,
experiment_ids: list[str] = list(),
created_at: str | None = None,
)
One hit from the Vertex-backed search.
methodic.SearchResponse
dataclass
¶
methodic.SearchFilters
dataclass
¶
SearchFilters(
asset_types: list[str] | None = None,
organization_id: str | None = None,
team_id: str | None = None,
created_after: str | None = None,
created_before: str | None = None,
created_by: str | None = None,
source_type: str | None = None,
tags: list[str] | None = None,
)
Filters layered on top of the RBAC + namespace filters the server adds.
methodic.AssetUploadInfo
dataclass
¶
Result of AssetsAPI.create_with_presigned: where to put each component.
Errors¶
methodic.ChronicleError ¶
Bases: Exception
Base class for every error raised by the methodic client.