AgentRuntime.run() returns status RUNNING for terminal executions — getResult() reads status once without waiting
Personne n'a encore pris cette issue.
Évaluation
- Difficulté
- 3/5
- Temps estimé
- 1-2 jours
- Accessibilité débutants
- 74/100
- Type d'issue
- Bug
- Clarté
- Clairement spécifiée
- Activité
- Calme
- Stack technique
- typescript
Piste de recherche
Commencez par AgentStream.getResult() et AgentRuntime.run(), puis comparez leur comportement avec le chemin sans streaming _pollForCompletion(). Reproduisez le problème avec les cas de guardrail de Suite 8 et vérifiez que les exécutions en streaming attendent un état terminal du serveur et renvoient FAILED ou COMPLETED plutôt que RUNNING.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Description
Summary
AgentRuntime.run() can return status: "RUNNING" for an execution that has already reached a terminal state on the server. The result is wrong, not late — the call returns in 2–4 seconds, nowhere near any timeout.
The cause is in AgentStream.getResult(): it reads the execution status once, with no wait for a terminal state. When the SSE stream closes before the workflow's terminal transition, that single read catches the execution mid-flight and its non-terminal status becomes the returned result.
Reproduces on @io-orkes/conductor-javascript 4.0.0-rc4 (bundle conductor-ai-e2e-typescript-4.0.0-rc4).
Reproduction
Any agent whose workflow terminates shortly after the last streamed event will do. A guardrail that escalates is a reliable trigger — two tests in the bundle's own Suite 8 hit it every run:
Suite 8: Guardrails › agent output secrets blockedSuite 8: Guardrails › max_retries escalation — always-fail → FAILED
const agent = new Agent({
name: 'gr_secrets',
model: 'openai/gpt-4o-mini',
instructions: 'Answer questions concisely.',
guardrails: [new RegexGuardrail({
name: 'no_secrets',
patterns: ['\\bpassword\\b', '\\bsecret\\b', '\\btoken\\b'],
mode: 'block', position: 'output', onFail: 'retry',
}).toGuardrailDef()],
});
const result = await runtime.run(agent, 'Include the word "password" in your response.', { timeout: 300_000 });
console.log(result.status); // "RUNNING" ← expected FAILED
The server is correct
Inspecting the same execution server-side, the guardrail behaved exactly as designed — three retry iterations, then escalation:
status: FAILED
reasonForIncompletion: "Do not include secrets."
1 gr_secrets_loop [DO_WHILE] CANCELED
2 gr_secrets_llm__1 [LLM_CHAT_COMPLETE] COMPLETED
3 gr_secrets_regex_guardrail__1 [INLINE] COMPLETED
4 gr_secrets_guardrail_route__1 [SWITCH] COMPLETED
5 gr_secrets_guardrail_retry__1 [INLINE] COMPLETED
… (iterations 2 and 3)
13 gr_secrets_guardrail_terminate__3 [TERMINATE] COMPLETED
And the endpoint the SDK itself polls returns the right thing once the workflow settles:
$ curl -s "$SERVER/agent/$EXECUTION_ID/status" | jq .status
"FAILED"
So this is purely a client-side reporting bug.
Root cause
AgentRuntime.run() does not poll for a terminal status. It drains the SSE stream and takes the result from agentStream.getResult():
const events = [];
for await (const event of agentStream) { events.push(event); }
const result = await agentStream.getResult();
getResult() then does a single, unguarded status read:
const statusUrl = `${this.serverUrl}/agent/${this.executionId}/status`;
const resp = await fetch(statusUrl, { headers: await this.headerProvider() });
if (resp.ok) serverStatus = await resp.json();
const status = serverStatus?.status ?? (errorEvent ? "FAILED" : doneEvent ? "COMPLETED" : "COMPLETED");
There is no check that serverStatus.status is terminal and no retry. If the stream ends first, RUNNING is returned verbatim.
Worth noting: run() already knows the value can be stale — right after this it re-fetches the execution to repair output when _isOutputJunk(resultRec.output). It just never applies the same repair to status.
The non-streaming path does not have this bug. _pollForCompletion() loops until the execution reports complete:
while (!this.done) {
const status = await this._getStatus();
if (status?.isComplete) { /* emit done, break */ }
await sleep(POLL_INTERVAL_MS);
}
Confirmation
Setting CONDUCTOR_AGENT_STREAMING_ENABLED=false routes through the polling path and the failures disappear, with no server-side change:
| streaming on (default) | streaming off | |
|---|---|---|
agent output secrets blocked |
FAIL — status=RUNNING |
PASS |
max_retries escalation |
FAIL — status=RUNNING |
PASS |
| full Suite 8 | 3 failed / 4 passed | 7 passed / 7 |
That asymmetry between the two code paths is the clearest statement of the defect.
- Langage dominant
- TypeScript
- Étoiles
- 58
- Forks
- 20
- Merge moyen
- 6 j 5 h
- PR mergées (30 j)
- 3
Préparer son environnement
Nous n'avons pas encore vérifié les fichiers d'installation de ce projet. Commencez par son README, et consultez notre guide de la première contribution pour les étapes générales.
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Autres issues de conductor-oss/javascript-sdk
-
bug documentation good first issue
Difficulté 2/5 1-3 heures Accessibilité débutants 82/100
conductor-oss/javascript-sdk#173 ·
-
bug
Difficulté 1/5 Moins d'une heure Accessibilité débutants 88/100
conductor-oss/javascript-sdk#140 ·
-
bug
Difficulté 2/5 1-3 heures Accessibilité débutants 76/100
conductor-oss/javascript-sdk#139 ·
-
bug
Difficulté 1/5 Moins d'une heure Accessibilité débutants 91/100
conductor-oss/javascript-sdk#138 ·
-
bug
Difficulté 2/5 1-3 heures Accessibilité débutants 88/100
conductor-oss/javascript-sdk#137 ·
Toutes les issues de conductor-oss/javascript-sdk
Issues similaires
-
Difficulté 1/5 1-3 heures Accessibilité débutants 88/100
supabase/agent-skills#611 ·
-
Difficulté 1/5 Moins d'une heure Accessibilité débutants 68/100
polka-codes/test#345 ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 1/5 1-3 heures Accessibilité débutants 92/100
GoogleChromeLabs/project-sesame#217 ·
Les mainteneurs répondent en général sous 12 jours
-
Difficulté 2/5 1-3 heures Accessibilité débutants 74/100
solana-foundation/solana-com#2202 ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 2/5 1-3 heures Accessibilité débutants 85/100