import type { Api } from "@mariozechner/pi-ai"; import type { ExtensionAPI } from "@mariozechner/pi-coding-agent"; type ProviderPayload = Record; const OPENAI_PARALLEL_TOOL_CALL_APIS: ReadonlySet = new Set([ "openai-completions", "openai-responses", "openai-codex-responses", "azure-openai-responses", ]); function isRecord(value: unknown): value is ProviderPayload { return typeof value === "object" && value !== null; } function hasTools(payload: ProviderPayload): boolean { return Array.isArray(payload.tools) && payload.tools.length > 0; } export function addOpenAIApiParallelToolCallsToPayload(api: Api | undefined, payload: unknown): unknown { if (!api || !OPENAI_PARALLEL_TOOL_CALL_APIS.has(api)) { return payload; } if (!isRecord(payload) || !hasTools(payload) || payload.parallel_tool_calls !== undefined) { return payload; } return { ...payload, parallel_tool_calls: true, }; } export const PARALLEL_TOOL_CALLS_SECTION = ` ## Execution Strategy ### Parallel Tool Calls When multiple tool calls are independent, fire them ALL in the same turn. Sequential tool calls waste round-trips and slow down every task. - Multiple file reads in the same turn when you already know the paths - Multiple searches with different patterns fired simultaneously - Combining read operations with search operations when they gather independent context Before calling any tool, ask: "What other context will I need alongside this?" Then gather it all in one turn. ### Context Breadth Before Changes Before modifying any file, gather enough context to get the change right on the first try: 1. Read the target file and any files it directly depends on - understand the dependency chain 2. Find every reference to symbols you will change - know the blast radius 3. Check for related tests - know what might break 4. Read inline comments or docs explaining design choices - understand the why Multiple well-informed edits in one pass beats a cycle of edit-then-fix-then-fix-again. `; export default function openaiApiParallelToolCallsExtension(pi: ExtensionAPI): void { pi.on("before_provider_request", (event, ctx) => { return addOpenAIApiParallelToolCallsToPayload(ctx.model?.api, event.payload); }); pi.on("before_agent_start", async (event) => ({ systemPrompt: `${event.systemPrompt}\n${PARALLEL_TOOL_CALLS_SECTION}`, })); }