JavaScript Workflow
NativeWorkflowRuntime exposes the Rust workflow engine to Node.js. It is a low-level JSON-based API: you provide workflow agents plus JSON strings for task and workflow definitions, and the runtime returns JSON strings for workflow lists, responses, and persisted run state.
const { NativeEnkiAgent, NativeWorkflowRuntime } = require('@getenki/ai')
const researcher = new NativeEnkiAgent(
'Researcher',
'Return short factual notes.',
'ollama::qwen3.5:latest',
4,
'./.enki',
)
researcher.configureWorkflow('researcher', ['research'])
const writer = new NativeEnkiAgent(
'Writer',
'Turn notes into a concise summary.',
'ollama::qwen3.5:latest',
4,
'./.enki',
)
writer.configureWorkflow('writer', ['writing'])
const tasksJson = [
JSON.stringify({
id: 'research_topic',
target: { type: 'capabilities', value: ['research'] },
prompt: 'Research {{topic}} and return 3 concise bullet points.',
input_bindings: { topic: 'input.topic' },
}),
JSON.stringify({
id: 'write_summary',
target: { type: 'agent_id', value: 'writer' },
prompt: 'Write a short summary for {{topic}} using {{research.content}}',
input_bindings: {
topic: 'input.topic',
research: 'research',
},
}),
]
const workflowsJson = [
JSON.stringify({
id: 'research-to-summary',
name: 'Research To Summary',
nodes: [
{ id: 'research', kind: 'task', task_id: 'research_topic', output_key: 'research' },
{ id: 'summary', kind: 'task', task_id: 'write_summary', output_key: 'summary' },
],
edges: [{ from: 'research', to: 'summary', transition: { type: 'always' } }],
}),
]
async function main() {
const runtime = new NativeWorkflowRuntime([researcher, writer], tasksJson, workflowsJson, './.enki')
const response = JSON.parse(
await runtime.startJson(
JSON.stringify({
workflow_id: 'research-to-summary',
input: { topic: 'workflow bindings in enki-js' },
}),
),
)
const persisted = JSON.parse(await runtime.inspectJson(response.run_id))
console.log(persisted.status)
}
main().catch(console.error)
See the full runnable workflow sample in example/basic-ts/agent-workflow.ts.
Human Intervention
Workflow runs persist pending interventions as part of the run state, so approvals and failure escalations can pause and resume without moving state into a separate coordinator service.
Each pending intervention includes:
workflow_idrun_idnode_idpromptreasonresponsecreated_atandresolved_at
Two built-in patterns are supported:
human_gatenodes pause immediately and wait for a human response- task nodes with
failure_policy: "pause_for_intervention"convert a terminal failure into an intervention asking the human toretry,skip,continue, orfail
The runnable interactive example is example/basic-ts/human-intervention-workflow.ts. It waits on stdin before resolving each intervention.
It demonstrates:
- a
human_gateapproval flow that pauses, resolves, and resumes toapproval.approved = true - a missing-agent failure that pauses for intervention and resumes after a human response such as
skip
The runtime interaction loop is:
startJson(...)returns a paused workflow responseinspectJson(runId)exposespending_interventions- read the intervention prompt and collect human input
submitInterventionJson(runId, interventionId, response)resolves the interventionresumeJson(runId)continues the persisted run
Current workflow methods:
listWorkflowsJson()listRunsJson()inspectJson(runId)startJson(requestJson)resumeJson(runId)submitInterventionJson(runId, interventionId, response?)