Child task composition: sequential execution and controlled parallelism
Reuse createChild and the shared budget, check every result, and commit in declaration order.
runChildren defaults its concurrency to the root Runner's maxConcurrentCalls. Each task explicitly configures visible transports, a call limit, and the amount reserved for the parent, and the result array keeps declaration order.
accept checks each result; the optional commit is only called after everything is accepted. A failure cancels the tasks in the group, and late results cannot be committed. When the whole set needs a transaction, the App handles the returned array inside a real transaction; commits that already happened are not rolled back by cancellation.
Progressive examples for the same business case
Analyze two documents in sequence
Beginner · Node.js
import { ModelRunner, Support } from '@jangts/agent-core';
import type { ChatProvider } from '@jangts/agent-core';
export async function analyze(provider: ChatProvider, inputs: readonly [string, string], signal: AbortSignal) {
const model = new ModelRunner({ provider, maxCalls: 5, execution: { signal } });
return Support.runChildren(model, inputs.map((input, index) => ({
id: 'analysis-' + index, maxCalls: 2, reserveCalls: 1, timeoutMs: 30000, transports: [],
async run(child: ModelRunner) { return (await child.invoke(input)).value; },
})), {
accept(value) { if (!value.trim()) throw new Error('分析结果为空'); },
});
}import { ModelRunner, Support } from '@jangts/agent-core';
export async function analyze(provider, inputs, signal) {
const model = new ModelRunner({ provider, maxCalls: 5, execution: { signal } });
return Support.runChildren(model, inputs.map((input, index) => ({
id: 'analysis-' + index, maxCalls: 2, reserveCalls: 1, timeoutMs: 30000, transports: [],
async run(child) { return (await child.invoke(input)).value; },
})), {
accept(value) { if (!value.trim())
throw new Error('分析结果为空'); },
});
}Add concurrent capacity to the same set of analyses
Configuration · Node.js
The same function and task list, adding only the root Runner capacity setting. Local budgets and the parent reservation still apply.
import { ModelRunner, Support } from '@jangts/agent-core';
import type { ChatProvider } from '@jangts/agent-core';
export async function analyze(provider: ChatProvider, inputs: readonly [string, string], signal: AbortSignal) {
const model = new ModelRunner({ provider, maxCalls: 5, execution: { signal }, children: { maxConcurrentCalls: 2 } });
return Support.runChildren(model, inputs.map((input, index) => ({
id: 'analysis-' + index, maxCalls: 2, reserveCalls: 1, timeoutMs: 30000, transports: [],
async run(child: ModelRunner) { return (await child.invoke(input)).value; },
})), {
accept(value) { if (!value.trim()) throw new Error('分析结果为空'); },
});
}import { ModelRunner, Support } from '@jangts/agent-core';
export async function analyze(provider, inputs, signal) {
const model = new ModelRunner({ provider, maxCalls: 5, execution: { signal }, children: { maxConcurrentCalls: 2 } });
return Support.runChildren(model, inputs.map((input, index) => ({
id: 'analysis-' + index, maxCalls: 2, reserveCalls: 1, timeoutMs: 30000, transports: [],
async run(child) { return (await child.invoke(input)).value; },
})), {
accept(value) { if (!value.trim())
throw new Error('分析结果为空'); },
});
}