different-ai/openwork · warning · ApiError
agent_diagnostics_busy
agent_diagnostics_busy
Error message
Agent diagnostics are temporarily busy
What it means
This 429 error is thrown by reserveAgentDiagnosticsRun when the number of concurrent agent diagnostics runs on a single server config has reached AGENT_DIAGNOSTICS_MAX_IN_FLIGHT_PER_SERVER. Unlike error 330 (same key already reserved), this fires for any new key once the pool is full. It is a temporary capacity backpressure signal.
Source
Thrown at apps/server/src/server.ts:217
agentDiagnosticsLastRun.set(key, now);
}
function reserveAgentDiagnosticsRun(
config: ServerConfig,
actor: Actor | undefined,
workspaceId: string,
): () => void {
const key = agentDiagnosticsActorWorkspaceKey(actor, workspaceId);
const inFlight = agentDiagnosticsInFlightByServer.get(config) ?? new Set<string>();
agentDiagnosticsInFlightByServer.set(config, inFlight);
// Preserve the existing cooldown response for ordinary repeated attempts.
// A zero/expired cooldown still cannot bypass the in-flight reservation.
requireAgentDiagnosticsRateLimit(config, actor, workspaceId);
if (inFlight.has(key)) {
throw new ApiError(429, "agent_diagnostics_in_progress", "Agent diagnostics are already in progress");
}
if (inFlight.size >= AGENT_DIAGNOSTICS_MAX_IN_FLIGHT_PER_SERVER) {
throw new ApiError(429, "agent_diagnostics_busy", "Agent diagnostics are temporarily busy");
}
// The cooldown charge and reservation are synchronous, so no second request
// for this actor/workspace can slip in between them.
inFlight.add(key);
let released = false;
return () => {
if (released) return;
released = true;
inFlight.delete(key);
};
}
const OPENWORK_VOICE_REALTIME_TOOLS = [
{
type: "function",
name: "openwork_snapshot",
description: "Read the current OpenWork UI control snapshot: route, status, narration, and visible action metadata.",View on GitHub (pinned to 2b7df46e8a)
Solutions
- Reduce concurrency of diagnostics calls client-side (semaphore/queue)
- Retry after a delay using exponential backoff until a slot frees
- Stagger diagnostics runs across workspaces
- Raise AGENT_DIAGNOSTICS_MAX_IN_FLIGHT_PER_SERVER only if server capacity allows
Example fix
// before
await Promise.all(workspaces.map(w => runDiagnostics(w.id)));
// after
for (const w of workspaces) {
await withConcurrencyLimit(2, () => runDiagnostics(w.id));
} Defensive patterns
Strategy: retry
Validate before calling
// cap client concurrency below the server limit const MAX_CONCURRENT = 2; // < AGENT_DIAGNOSTICS_MAX_IN_FLIGHT_PER_SERVER if (outstandingDiagnostics >= MAX_CONCURRENT) await queue.wait();
Try / catch
try {
await reserveAgentDiagnosticsRun(config);
} catch (e) {
if (e.code === "agent_diagnostics_busy") {
await sleep(backoffMs);
return reserveWithRetry(config); // exponential backoff
}
throw e;
} Prevention
- Serialize diagnostics runs with a client-side semaphore
- Stagger scheduled diagnostics across workspaces
- Back off exponentially on 429 responses
When it happens
Trigger: POSTing a new agent diagnostics request (unique actor/workspace key) when inFlight.size >= AGENT_DIAGNOSTICS_MAX_IN_FLIGHT_PER_SERVER for that server config. Multiple distinct workspaces or actors starting diagnostics simultaneously.
Common situations: CI pipelines running diagnostics for many workspaces in parallel against one server; org-wide 'diagnose everything' scripts; bursts after a mass config change.
Related errors
- agent_diagnostics_in_progress
- plugin_fetch_failed
- automation_revision_changed
- automation_run_lease_lost
- connector_mapping_not_found
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/acfd481bb4f694c1.
Report an issue: GitHub.