fix(built-in-agents): pin summarizer to safe local adapter defaults

The Summarizer built-in template defaults to `claude_local` but omits
`adapterConfig.engine` and any `defaultRuntimeConfig`. When a company
provisions it, the resulting agent runs on the implicit engine and with
whatever heartbeat concurrency the harness picks up (which can be much
higher than 1 for local Claude/Codex adapters).

Local Claude/Codex agents are safe when they:
  1. Pin `adapterConfig.engine` to `cli` so the adapter uses the local
     Claude/Codex CLI transport instead of the SDK/HTTP path.
  2. Cap heartbeat concurrency at 1 so a single agent identity never
     spawns parallel runs that can race quota or state.

Both are already true for hand-provisioned local agents; the built-in
template shouldn't be the odd one out. Pinning them here also gives
adapter-level guards (that reject non-cli engines or concurrency > 1)
a stable default to target.

Changes:
  - server/src/services/built-in-agents.ts: add `engine: "cli"` to
    the summarizer's `defaultAdapterConfig` and set
    `defaultRuntimeConfig: { heartbeat: { maxConcurrentRuns: 1 } }`.
  - server/src/__tests__/built-in-agents.test.ts: update the static-
    registry assertion to expect the new defaults.

Scoped narrowly to the summarizer: it's the only built-in that ships
with a hardcoded `defaultAdapterType` today. The other built-ins
(briefs, learning, reflection-coach) resolve their adapter at
provisioning time and can be tightened in a follow-up if wanted.
This commit is contained in:
Builder · Ingeniería 2026-07-19 23:02:41 +00:00
parent f12bb27bcd
commit 00e837cff2
2 changed files with 6 additions and 2 deletions

View File

@ -161,9 +161,9 @@ describeEmbeddedPostgres("built-in agents", () => {
const summarizer = definitions.find((definition) => definition.key === "summarizer");
expect(summarizer).toMatchObject({
defaultAdapterType: "claude_local",
defaultAdapterConfig: { model: "claude-haiku-4-5" },
defaultAdapterConfig: { model: "claude-haiku-4-5", engine: "cli" },
defaultRuntimeConfig: { heartbeat: { maxConcurrentRuns: 1 } },
});
expect(summarizer?.defaultRuntimeConfig).toBeUndefined();
expect(() => validateBuiltInAgentDefinitions([
{
key: "briefs",

View File

@ -415,6 +415,10 @@ const DEFINITIONS = validateBuiltInAgentDefinitions([
defaultAdapterType: "claude_local",
defaultAdapterConfig: {
model: "claude-haiku-4-5",
engine: "cli",
},
defaultRuntimeConfig: {
heartbeat: { maxConcurrentRuns: 1 },
},
defaultBudgetMonthlyCents: 0,
bundle: {