Steps
runCode
Execute arbitrary async code as a typed step.
Quick Example
import { runCode } from '@noetic-tools/core';
const transform = runCode({
id: 'normalize-input',
execute: async (input: string, ctx) => {
return input.trim().toLowerCase();
},
});What It Does
runCode wraps any async function as a step. It is the escape hatch for custom logic -- API calls, database operations, file I/O, data transformations, or anything that is not a model call.
The execute function receives two arguments:
- input -- the typed input from the previous step (or the initial pipeline input).
- ctx -- the Noetic
Context, giving access to context, tokens, abort signals, and more.
The return value becomes the output of the step, passed to whatever comes next.
Type Signature
type RunCodeStepOptions<TContext, I, O> = {
id: string;
execute: (input: I, ctx: Context<TContext>) => Promise<O>;
retry?: RetryPolicy;
};
declare const stepRunCode: <TContext, I, O>(
opts: RunCodeStepOptions<TContext, I, O>,
) => StepRunCode<TContext, I, O>;TContext is the typed context shape (from InferContext), I is the input type, and O is the output type.
API Reference
Options
| Property | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique step identifier |
execute | (input: I, ctx: Context<TContext>) => Promise<O> | Yes | The async function to run |
retry | RetryPolicy | No | Retry configuration on failure |
subprocess | SubprocessAdapter | No | Per-step subprocess adapter override. When set, the interpreter dispatches this step through the given adapter instead of the harness default (resolution order: detachedSpawn overrides → step.subprocess → harness.subprocess) |
RetryPolicy
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
maxAttempts | number | Yes | -- | Maximum number of attempts |
backoff | 'fixed' | 'linear' | 'exponential' | Yes | -- | Backoff strategy between retries |
initialDelay | number | Yes | -- | Delay in ms before first retry |
maxDelay | number | No | -- | Cap on delay between retries |
Retry Example
import { runCode } from '@noetic-tools/core';
const fetchData = runCode({
id: 'fetch-api',
execute: async (url: string) => {
const res = await fetch(url);
if (!res.ok) {
throw new Error(`HTTP ${res.status}`);
}
return res.json();
},
retry: {
maxAttempts: 3,
backoff: 'exponential',
initialDelay: 1e3,
maxDelay: 1e4,
},
});Using Context
The Context object provides access to runtime state inside your execute function.
import { runCode } from '@noetic-tools/core';
const contextAware = runCode({
id: 'context-example',
execute: async (input: string, ctx) => {
// Check if the run has been cancelled
if (ctx.aborted) {
return 'Cancelled';
}
// Access token usage
console.log('Tokens used so far:', ctx.tokens.total);
// Access context layer data
const snapshot = ctx.context['scratchpad'].snapshot;
return `Processed: ${input}`;
},
});The ctx.context property provides typed access to data and functions exposed by context layers via their provides field. See Context for the full property reference.
Related
- callModel -- for language model calls.
- invokeTool -- for direct tool invocation.
- Loop & Until -- use
runCodeas a loop body for custom iteration logic.