refactor(agent-loop): unify tool-call scheduling on one rolling pool + factory cap default
Run every ordered group through the same rolling pool: an exclusive call is a pool of one (a barrier), dropping the separate runExclusive path and the redundant post-grouping executionMode re-query. Behavior is unchanged — the parallel-tool-calls snapshot and the full scheduler unit suite (barriers, cap, abort, model-order results) stay green. Add AgentLoop.Config.maxParallelToolCalls as a factory-wide default applied to every agent create/createAgent/resume mints (per-agent option overrides it), forwarded through agent-core so it reaches front doors that expose no cap field of their own. Trim the isConcurrencySafe JSDoc to the local contract and link the parallel-tool-call RFC for the full rationale; document the field on the canonical core-data-structures page.
This commit is contained in:
@@ -347,7 +347,7 @@ interface Agent {
|
||||
}
|
||||
```
|
||||
|
||||
`AgentStatus` is `'idle' | 'running' | 'disposed'`, and `AgentId` is branded. `AgentOptions` is merge-extensible and currently includes `model?`. Persona belongs to `dsh-system-prompt`: an agent-scoped `deployment:persona` may shadow the global default.
|
||||
`AgentStatus` is `'idle' | 'running' | 'disposed'`, and `AgentId` is branded. `AgentOptions` is merge-extensible and currently includes `model?` and `maxParallelToolCalls?` (the loop's per-agent concurrent tool-call cap; the owning field, defaulted by `AgentLoop.Config` and, absent that, by `DEFAULT_MAX_PARALLEL_TOOL_CALLS`). Persona belongs to `dsh-system-prompt`: an agent-scoped `deployment:persona` may shadow the global default.
|
||||
|
||||
The [event taxonomy](../architecture.md#event) owns the `agent/*` lifecycle, checkpoint, and waterfall contracts. Turn and step boundaries are durable session events rather than agent emits.
|
||||
|
||||
|
||||
@@ -30,20 +30,18 @@ interface ToolDefinition extends ToolSchema {
|
||||
*
|
||||
* It may inspect the parsed `args` (`unknown` — a hand-rolled definition
|
||||
* receives the raw parsed value; `defineTool` schema-validates first and
|
||||
* returns `false` on invalid args, so an eventual `ToolArgsError` is produced
|
||||
* only if the tool actually executes). The check performs no I/O and receives
|
||||
* no live `Agent` or mutable `ToolExecution`.
|
||||
* returns `false` on invalid args). The check performs no I/O and receives no
|
||||
* live `Agent` or mutable `ToolExecution`.
|
||||
*
|
||||
* Declaring `true` is a contract: the tool body must NOT mutate the parent
|
||||
* agent's session or other parent-owned async state during `execute` (no
|
||||
* `exec.agent.session.append(...)`, no `agent.inject(...)`). Its only parent-
|
||||
* Declaring `true` is a contract: during `execute` the tool body must NOT
|
||||
* mutate the parent agent's session or other parent-owned async state (no
|
||||
* `exec.agent.session.append(...)`, no `agent.inject(...)`); its only parent-
|
||||
* step outputs are the returned content, `meta`, structured error, and
|
||||
* `additionalContext` carried through the loop's ordered post-execute path.
|
||||
* The narrow exception is a synchronous, side-effect-only recorder whose
|
||||
* updates are commutative OR fail closed for concurrent calls by the same
|
||||
* session (the `fs/observed` version recorder is the worked example: its
|
||||
* WeakMap record is last-writer-wins, and a stale observation only makes a
|
||||
* later write/edit fail closed at its in-lock version CAS).
|
||||
* `additionalContext` on the loop's ordered post-execute path. A synchronous,
|
||||
* side-effect-only recorder whose updates are commutative or fail closed for
|
||||
* concurrent same-session calls is the one exception (`fs/observed` is the
|
||||
* worked example). Full contract and rationale: the parallel-tool-call RFC
|
||||
* (docs/rfc/implemented/feature/2026-07-10-parallel-tool-call-execution.md).
|
||||
*/
|
||||
isConcurrencySafe?(args: unknown): boolean
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user