Parallel Execution¶
AgentLang has first-class syntax for running tasks concurrently. The parallel { } join block executes multiple run statements at the same time and makes all their results available after the join.
Syntax¶
parallel [ max_concurrency <N> ] {
let a = run task_name with { ... } by agent;
let b = run task_name with { ... } by agent;
} join;
Example¶
From examples/compare.agent:
pipeline compare_options(query: String) -> String {
parallel {
let a = run research with { topic: query + " option A" } by planner;
let b = run research with { topic: query + " option B" } by planner;
} join;
let c = run compare with { note_a: a.notes, note_b: b.notes } by reviewer;
return c.decision;
}
{
"result": "[reviewer] Option A vs B\nA: [planner] key points for 'vector database option A'\nB: [planner] key points for 'vector database option B'"
}
The two research calls ran at the same time. After join, both a and b are available for the downstream compare step.
How it works¶
- The runtime takes a snapshot of the current environment at the start of the block.
- Each branch runs in its own thread via
ThreadPoolExecutor. - After all futures complete, branch outputs are merged into the main environment.
- Execution continues sequentially after
join.
Rules¶
- Only
let ... = run ...;statements are permitted inside aparallelblock.if,return, and nestedparallelblocks are not allowed. - All branch bindings become available after
join. - Branches share a read-only snapshot of the environment — they cannot see each other's outputs until after
join.
Controlling concurrency¶
There are two levels of concurrency control:
Global: The --workers flag sets the maximum number of concurrent threads across all parallel blocks:
python main.py examples/compare.agent compare_options \
--input '{"query":"vector database"}' \
--workers 4
The default is 8. The value must be >= 1.
Per-block: The optional max_concurrency clause limits how many branches run simultaneously within a single parallel block:
parallel max_concurrency 2 {
let a = run research with { topic: "angle A" } by planner;
let b = run research with { topic: "angle B" } by planner;
let c = run research with { topic: "angle C" } by planner;
} join;
With max_concurrency 2, at most 2 of the 3 branches execute at the same time. This is useful for rate-limiting API calls or controlling resource usage within a specific block without affecting other parallel blocks.
Thread safety¶
Task handlers in agentlang/stdlib.py that share mutable state use a threading.Lock. If you write a custom task handler that mutates shared state, protect it with a lock.