Force agents to act so weak models can't complete a no-op
The whole premise is cheap models + skills + a team — so the control plane, not the model, must guarantee action. Every adapter hardcoded tool_choice:"auto", letting a weak model answer the kickoff with prose and "succeed" having hired no one, delegated nothing, and said nothing. Now the agent loop compels a tool call on the opening turn (tool_choice plumbed through every backend: OpenAI/Responses/Chat, Anthropic, Codex, Copilot, Azure, Custom, Gemini ANY mode, Bedrock any). If the forced turn still yields no tool call, the run fails loudly instead of recording a deceptive success — surfacing the problem (let it crash) rather than a silent dead company. After it has acted, the model chooses freely. Tested: a stub that rambles on "auto" but acts when forced now posts a kickoff message; a prose-only first turn fails the run. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
fa01aa682f
commit
ef9ee463c9
9 files changed
+107
-35
No files matched your search
@@ -12,7 +12,7 @@ import type { ProviderRateLimitRegistry } from "./provider-rate-limit-registry";
|
||||
import type { ProviderRequestStore } from "./provider-request-store";
|
||||
import type { ProviderResponseObserver } from "./provider-response-observer";
|
||||
import { hashPrompt, readProviderResponseId, requireStreamText } from "./provider-response-utils";
|
||||
import { type AgentTurnMessage, type AgentTurnResult, type ToolDefinition, type ToolTurnFn } from "./provider-tool-turn";
|
||||
import { type AgentTurnMessage, type AgentTurnResult, type ToolChoice, type ToolDefinition, type ToolTurnFn } from "./provider-tool-turn";
|
||||
import { selectToolTurn, supportsToolTurn } from "./provider-tool-turns/router";
|
||||
import { resolveTurnCredential } from "./provider-tool-turns/credential-resolver";
|
||||
import {
|
||||
@@ -103,6 +103,7 @@ export class ProviderResponseRunner {
|
||||
instructions: string | null;
|
||||
messages: AgentTurnMessage[];
|
||||
tools: ToolDefinition[];
|
||||
toolChoice?: ToolChoice;
|
||||
}): Promise<AgentTurnResult & { requestId: string }> {
|
||||
const provider = loadConfiguredProvider(this.deps.db, input.orgId, input.providerId);
|
||||
const workspaceId = this.normalizeWorkspaceId(input.orgId, input.workspaceId ?? null);
|
||||
@@ -128,7 +129,7 @@ export class ProviderResponseRunner {
|
||||
});
|
||||
const startedAt = Date.now();
|
||||
try {
|
||||
const result = await turn({ credential, model, instructions: input.instructions, messages: input.messages, tools: input.tools });
|
||||
const result = await turn({ credential, model, instructions: input.instructions, messages: input.messages, tools: input.tools, toolChoice: input.toolChoice });
|
||||
this.deps.requestStore.markSucceeded({
|
||||
orgId: input.orgId,
|
||||
requestId,
|
||||
|
||||
Reference in new issue
Block a user