Activity kinds reference
Full API templates and rules for all five activity kinds — cli, mcp_tool, code, llm, and builtin.
cli
Runs a shell command or external binary.
Template:
import { step } from '@cori-do/sdk';
import { z } from 'zod';
export const input = z.object({
// define step inputs
});
export const output = z.object({
// define step outputs
});
export default step.cli({
description: 'What this step does',
command: ({ input }) => `your-binary --flag ${input.some_value}`,
parse_output: (stdout) => ({
// parse stdout into output shape
}),
});Rules:
- Declare the binary in the manifest's
tools_required. Validated atcori checktime. - If the binary is not found on
PATH, runcori statusto check the worker's environment. - Default retry: 1 attempt (transient failures are not automatically retried).
- Default per-attempt timeout: 60 seconds.
mcp_tool
Calls a tool on an MCP server.
Template:
import { step } from '@cori-do/sdk';
import { z } from 'zod';
export const input = z.object({
// define step inputs
});
export const output = z.object({
// define step outputs
});
export default step.mcp_tool({
description: 'What this step does',
server: 'server-name', // must match mcp_servers in manifest
tool: 'tool_name',
args: ({ input }) => ({
// tool arguments
}),
parse_output: (result) => ({
// parse MCP result into output shape
}),
});Rules:
- Declare the MCP server in the manifest's
mcp_servers. Validated atcori checktime. - Default retry: 1 attempt.
- Default per-attempt timeout: 60 seconds.
code
Pure TypeScript computation with no I/O.
Template:
import { step } from '@cori-do/sdk';
import { z } from 'zod';
export const input = z.object({
// define step inputs
});
export const output = z.object({
// define step outputs
});
export default step.code({
description: 'What this step does',
run: ({ input }) => {
// pure computation — no network, no filesystem, no shell
return {
// output shape
};
},
});Rules:
Never put external I/O in a code step. No network calls, no filesystem reads, no shell commands. Code steps run in the Temporal workflow execution context and must be deterministic pure functions.
- Default retry: 3 attempts.
- Default per-attempt timeout: 30 seconds.
What a code step may import. Steps run in a Deno subprocess launched with a fixed import map containing exactly two entries — @cori-do/sdk and zod — resolved against that map, never against any node_modules.
- Default: import only
@cori-do/sdk,zod, and JS/Web/Deno globals that need no import (JSON,Intl,Date,Math,Map/Set,structuredClone,TextEncoder,crypto.subtle,URL, …). Most pure transforms need nothing more. node:*imports are forbidden —cori checkrejects them with a hard error, and the sandbox lacks the permissions those modules want.- Need a third-party library? Use an explicit registry specifier, not a bare name:
npm:<pkg>@<ver>,jsr:<scope>/<pkg>, orhttps://esm.sh/<pkg>@<ver>. The package must be pure JS/Wasm — native addons or anything touchingnode:fs/net/child_processfails under the sandbox. A bareimport _ from 'lodash'does not work; it must beimport _ from 'npm:lodash@4'. Testing withdeno testcatches a bad bare import before runtime, because tests resolve against the same import map.
llm
Calls a language model with a prompt and parses the typed output.
Template:
import { step } from '@cori-do/sdk';
import { z } from 'zod';
export const input = z.object({
// define step inputs
});
export const output = z.object({
// define step outputs — required for llm steps
});
export default step.llm({
description: 'What this step does',
model: 'gpt-4o-mini',
prompt: ({ input }) => `Your prompt here. Data: ${JSON.stringify(input)}`,
output_schema: output,
// optional:
system: 'You are a helpful assistant.',
});Rules:
output_schemais required. LLM steps must declare a typed output.- Use
llmonly for content that varies at runtime (translation, classification, extraction). - Provider credentials are configured at the worker level, not in the step file.
- Default retry: 3 attempts.
- Default per-attempt timeout: 300 seconds.
builtin — deferred in v1
builtin steps are accepted by the compiler but the v1 runtime does not execute them. The constructors below are documented for reference only. Do not use them in workflows you intend to run today.
The builtin constructors provide workflow-level control flow:
| Constructor | Description |
|---|---|
step.builtin.map(...) | Fan out over a list, run a step per item |
step.builtin.for_each(...) | Iterate over items sequentially |
step.builtin.branch(...) | Conditional execution |
step.builtin.parallel(...) | Run multiple steps concurrently |
step.builtin.wait(...) | Wait for an external event or signal |
These will be executable in a future version of Cori.

