latent.studio_client¶
HTTP client for Agent Studio API.
Classes¶
ConversationListResponse¶
Paginated response from the conversations endpoint.
ConversationSummary¶
Conversation metadata from the list endpoint, used in eval report summaries.
DatasetSummary¶
Dataset metadata returned by the list endpoint.
StudioClient¶
Thin HTTP client for Agent Studio API.
Methods¶
ConversationSummary.message_count¶
ConversationSummary.score¶
ConversationSummary.status¶
StudioClient.create_dataset¶
create_dataset(slug: str, display_name: str, type_: DatasetType, source: DatasetSource = 'upload', description: str | None = None, tags: list[str] | None = None) -> str
Create a new empty dataset via POST /api/datasets/.
Returns the new Convex dataset_id so the caller can chain
directly into :meth:upload_records (which resolves slug → id
again on its own, but the id is useful when the caller already
has it for logging / scripted-followups).
Use this once per slug as a setup step before the first
:meth:upload_records. The agent-studio UI's "Create Dataset"
dialog calls the Convex mutation directly without going through
this HTTP route, so existing UI-created datasets need no
migration.
Raises:
ValueError: on 404 (route missing on an older backend), 409
(duplicate slug — message names the offending slug), or
a malformed 2xx response missing dataset_id.
RuntimeError: on 429 (rate limit) or any other server-side
failure that _send doesn't already translate.
Args:
slug: Unique short name used in URLs and CLI commands.
Server enforces [a-zA-Z0-9._-]+ and 1-128 chars; bad
slugs return 422.
display_name: Human-readable label shown in the studio UI.
Server enforces 1-256 chars; empty / whitespace returns 422.
type_: One of "conversation", "qa_pair", "generic",
"file_bundle". Determines which record-shape
validation the upload path applies. For eval-results rows
"generic" is the right choice.
source: One of "upload", "curated", "disk",
"mixed". Defaults to "upload" (the only
CLI-relevant value).
description: Optional human-readable description shown in UI.
tags: Optional dataset-level tags (separate from per-version
tags managed via :meth:tag_version).
Note:
The Convex datasets:create mutation also accepts
recordSchema (Pydantic-style per-field validators), but
the HTTP route doesn't expose it yet and neither does this
method. TODO: expose when there's a concrete caller.
StudioClient.download_conversations¶
download_conversations(mode: str | None = None, date_from: str | None = None, date_to: str | None = None, feedback: str | None = None, min_score: int | None = None, max_score: int | None = None, limit: int = 5000, annotations: bool = False) -> bytes
Download conversations as JSONL, following the export cursor.
The endpoint soft-limits each response and returns an X-Next-Cursor
header while the stream isn't exhausted, so one selective export can
span several requests. Follow the cursor until it's gone or limit
rows have been collected, and return the concatenated JSONL bytes.
StudioClient.download_dataset¶
StudioClient.download_dataset_by_tag¶
Fetch the version of slug most-recently tagged tag.
Use this for the "comparison baseline" path — e.g. tag="production"
always returns whatever version was last promoted. Pin to a specific
version by passing version=... to :meth:download_dataset instead.
StudioClient.list_conversations¶
list_conversations(mode: str | None = None, date_from: str | None = None, date_to: str | None = None, feedback: str | None = None, min_score: int | None = None, max_score: int | None = None, limit: int = 50, cursor: str | None = None) -> ConversationListResponse
StudioClient.list_datasets¶
StudioClient.resolve_dataset_id¶
Look up the Convex _id of a dataset by slug.
Needed because the upload + publish routes are keyed on the internal ID, not the slug. Raises ValueError if the slug is unknown.
StudioClient.resolve_version¶
StudioClient.tag_version¶
Attach tag to a specific version of slug.
exclusive=True is the singleton-tag mode used for promotion
labels like production: every other version of the same
dataset loses the tag first. exclusive=False (the default)
leaves other versions alone and is the right choice for
multi-version labels like branch:feat-x.
StudioClient.untag_version¶
Remove tag from a specific version. Idempotent.
The tag is URL-encoded into the path because tags can contain
slashes (e.g. "branch/my-feature") or other URL-unsafe
characters that would otherwise silently malform the request.
tag_version doesn't need this — it sends tag in the JSON
body, not the path.
StudioClient.upload_records¶
upload_records(slug: str, records: list[dict[str, Any]], published_by: str | None = None, filename: str = 'records.jsonl') -> int
Append records to slug as a new published version.
Two-step under the hood: upload to draft (validates + writes blob), then publish (promotes draft to version N+1). Returns the new version number on success.
Failure between the two steps leaves a dangling draft on the server — we deliberately don't try to clean it up because the most likely cause is a network or auth failure where the cleanup call would also fail. The draft is overwritten by the next successful upload, so callers don't need to take action.
Callers must ensure the dataset exists (use a one-time latent
studio datasets create or the agent-studio UI). The dataset's
type (generic/qa_pair/conversation) gates which
record fields are validated; for eval-results rows generic is
the right type.