Client reference
Constructing
const shimmy = new Shimmy(); // reads the environment
const shimmy = new Shimmy({ apiKey, baseUrl }); // or explicit | Option | Default | Notes |
|---|---|---|
apiKey | SHIMMY_API_KEY, then OPTIMIZER_API_KEY | Required. |
baseUrl | SHIMMY_BASE_URL, then OPTIMIZER_BASE_URL | Defaults to https://rfa-labs.com. |
sourceContext | true | Attach file, line and release to each call. |
release | auto-detected | From SHIMMY_RELEASE, GITHUB_SHA, GIT_COMMIT, … |
objective | — | cost, quality, or latency. |
onError | warn | Where 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
| TypeScript | Python | Rust | |
|---|---|---|---|
Across await | automatic | automatic | automatic |
| Into a spawned task | automatic | automatic | explicit parent |
| Current ids | currentRunId() | current_run_id() | current() |
Rust’s task-locals do not survive tokio::spawn. See instrument an agent.