Client reference

Constructing

const shimmy = new Shimmy();                    // reads the environment
const shimmy = new Shimmy({ apiKey, baseUrl }); // or explicit
OptionDefaultNotes
apiKeySHIMMY_API_KEY, then OPTIMIZER_API_KEYRequired.
baseUrlSHIMMY_BASE_URL, then OPTIMIZER_BASE_URLDefaults to https://rfa-labs.com.
sourceContexttrueAttach file, line and release to each call.
releaseauto-detectedFrom SHIMMY_RELEASE, GITHUB_SHA, GIT_COMMIT, …
objectivecost, quality, or latency.
onErrorwarnWhere telemetry failures go.

Scopes

run(name, fn, { id }) — opens a run. id resolves itself (an active OpenTelemetry trace id, else a uuid); pass one only when a request is not one run, such as a batch job where each item is its own.

step(id, options, fn) — opens a step. Options: kind, name, minScore, loopIndex, isRetry, mode ("discover" / "off"), latencyBudgetMs, objective.

TypeScript and Python take a callback or a context manager, so the scope closes itself. Rust returns a guard that closes on drop — RAII rather than a callback, because ? makes early returns idiomatic and a hand-closed scope would leak on the first error path someone wrote.

await shimmy.run('r', async () => {
  await shimmy.step('classify', { kind: 'classification' }, async () => {
    // …
  });
});

Opening a step outside a run starts an implicit single-step run rather than failing — partial instrumentation should degrade, not break.

Decorating a client

wrap(client) (TypeScript, Python) — returns your client, repointed and annotated. Nothing is reimplemented, so unmodelled features keep working.

Python rides on extra_body, which is openai-python’s documented channel for unmodelled fields — so it survives version churn that would break a patched method. TypeScript patches the method, because JS has no equivalent.

instrument_openai(shimmy) (Python only) — a global patch for clients constructed inside a framework you do not own. Returns an undo callable, so test suites stay clean. It does not repoint base_url; it cannot know which clients in the process are meant for the optimizer.

decorate(&mut body) (Rust) — merges annotations into a JSON body. Rust has no dominant OpenAI client, so the seam is the request body rather than a wrapper. Returns whether anything was attached.

Reporting

report(signals, { stepId, runId }) — see report outcomes.

verify(fn, kind) — runs fn, reports success or failure, rethrows. For where “did it work” is “did it throw”.

Best-effort: failures are logged, never thrown.

Reading the accounting

import { optimizerMeta } from '@rfa-labs/shimmy';

const meta = optimizerMeta(res);
meta?.saving;             // baseline − actual
meta?.exploration_cost;   // paid to learn; → 0 as the step settles

Escaping the scope

TypeScriptPythonRust
Across awaitautomaticautomaticautomatic
Into a spawned taskautomaticautomaticexplicit parent
Current idscurrentRunId()current_run_id()current()

Rust’s task-locals do not survive tokio::spawn. See instrument an agent.