Start
← Relifold documentation

Quickstart

Create and run a reviewed semantic pipeline from Python.

1. Install the Python client

Use Python 3.9 or later in a clean virtual environment or notebook kernel. The client has no third-party runtime dependencies. It connects to hosted Relifold; no repository checkout, AWS credentials or model-provider keys are needed. Do not install the internal scratchpad server package alongside relifold-client: they share a Python namespace.

python -m pip install "https://relifold.com/downloads/relifold_client-0.2.2-py3-none-any.whl"

Inside Jupyter, install into the current kernel:

%pip install "https://relifold.com/downloads/relifold_client-0.2.2-py3-none-any.whl"

Download the complete notebook. It includes a small dataset and the full sample → review → estimate → declare → run journey. If you do not have Jupyter, install JupyterLab in your virtual environment and open the notebook:

python -m pip install jupyterlab
python -m jupyterlab

2. Connect with your Relifold API key

Create and confirm an account at app.relifold.com, open your workspace, and create a key from its API keys page. Store the key in RELIFOLD_API_KEY or enter it using a masked prompt. Do not put it in notebook source.

import os
from getpass import getpass
from scratchpad.api import ScratchpadClient

account = ScratchpadClient(os.environ.get("RELIFOLD_API_KEY") or getpass("Relifold API key: "))
workspace = account.select_workspace()
print(account.billing(workspace.organization_id))

For multiple organizations/workspaces, pass an ID, slug or name as organization= and workspace=. Before starting paid work, check your organization's execution credit and spending limit. A provider account balance does not fund your Relifold workspace. The notebook sets a dollar limit for each paid request; the automated review's spend counts against your organization's credit.

3. Upload and author

Upload a CSV, JSON or JSONL file, or a list of rows, into a named dataset. Then ask the Planner to create an editable draft; the call returns once the draft is registered.

workspace.upload("materials", path="materials.csv")
result = workspace.plan(
    pipeline_id="material-groups", version_id="v1", sources=["materials"],
    instruction="Group names for the same material; preserve distinct materials and blends.",
    max_authoring_cost_usd=3.0,
)
print(result)

Inspect the draft with workspace.version(pipeline_id, version_id) and workspace.prompts(pipeline_id, version_id). To change a draft, register its edited declaration again with workspace.register_version(spec). Each node in the spec is a node as workspace.version returns it, or its constructor written as text, such as "SemFilter(name=..., ...)". Operator constructor examples describe definitions submitted to the service; the hosted SDK does not execute operators locally.

4. Sample, review and compare

The notebook creates a Workbench group and samples it. Relifold's reviewer then answers 20 cards in the background while you label three yourself; a review created with trust_reviewer=True counts toward the estimate. Reviewed-card measurements describe those cards; estimates describe the full input and include both a point and range. A small tutorial sample does not establish quality on your production data.

group = workspace.workbench_group(pipeline_id, version_id, group_id)
group.create_review(cards=20, seed=1, selection="balanced", trust_reviewer=True)
group.label_samples(cards=3, selection="balanced")
group.fetch_estimate()
group.fetch_estimate({f"{task_id}.confidence_threshold": 0.7})

Use the task and group IDs shown by your draft. Requesting a changed estimate neither saves parameters nor launches a full execution. See the notebook for the complete, executable sequence.

5. Declare, run and inspect

A draft is editable. Declaration freezes it and ends its disposable research phase, so finish reviewing and comparing first. A later change belongs in an editable successor. Run starts a single execution; deployment separately creates a recurring schedule.

workspace.declare_version(pipeline_id, version_id)
result = workspace.run(pipeline_id, version_id, max_cost_usd=1.0)
rows = workspace.rows(session_id=result["session_id"])

run waits for the run and prints how it went; rows returns every output row. Use launch to start a run without waiting. The notebook makes scheduling an explicitly confirmed final action; closing a notebook does not cancel a recurring deployment.

Interruptions and slow requests

run waits by reading the run it started. A timeout or keyboard interrupt stops local waiting only; workspace.session(session_id) reads the run later. Ordinary requests have a short deadline, while synchronous estimates, reviewer and advice requests have a longer one. An explicit timeout_seconds on the client overrides these defaults.

Paid submissions receive recovery IDs and are never automatically retried. A lost response raises RequestInterruptedError with a request_id. A keyboard interruption displays the ID; workspace.last_request_id also retains it. Save the ID before replacing your notebook kernel.

If you lost the ID, workspace.recent_requests() lists your currently authorized requests with their operation, pipeline and submission time. Follow next_offset for earlier requests. Listing requests does not start or resume paid work.

Call workspace.wait_for_request(request_id) to recover the original JSON API response without submitting more work. This read also works from a newly connected client. If the recovered response identifies a run, read it with workspace.session(session_id). Recovery does not turn an error into success.

If the service reports an interrupted request, its outcome remains unknown. Inspect the pipeline results or contact support with the request ID instead of resubmitting. A missing receipt likewise does not prove the original request never arrived.

For direct HTTP clients, send a unique Idempotency-Key on paid JSON submissions. Reusing it identifies the same request; changing its content is rejected. Recover its response through GET /o/{organization}/w/{workspace}/api/v1/requests/{request_id}. The Python SDK supplies these identifiers automatically.

Next

Read Spaces, Workbench, and the operator chooser.