AgentRuntime.run() returns status RUNNING for terminal executions — getResult() reads status once without waiting
Nobody has claimed this yet.
Assessment
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Newbie friendliness
- 74/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Quiet
- Tech stack
- typescript
Research direction
Start at AgentStream.getResult() and AgentRuntime.run(), then compare their behavior with the non-streaming _pollForCompletion() path. Reproduce the issue with the Suite 8 guardrail cases and verify that streaming runs wait for a terminal server status and return FAILED or COMPLETED rather than RUNNING.
Written by the indexing model from the issue text.
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.
- Dominant language
- TypeScript
- Stars
- 58
- Forks
- 20
- Avg merge
- 6d 5h
- Merged PRs (30d)
- 3
Getting set up
We have not checked this project's setup files yet. Start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from conductor-oss/javascript-sdk
-
bug documentation good first issue
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
conductor-oss/javascript-sdk#173 ·
-
bug
Difficulty 1/5 Under an hour Newbie friendliness 88/100
conductor-oss/javascript-sdk#140 ·
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
conductor-oss/javascript-sdk#139 ·
-
bug
Difficulty 1/5 Under an hour Newbie friendliness 91/100
conductor-oss/javascript-sdk#138 ·
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
conductor-oss/javascript-sdk#137 ·
All issues in conductor-oss/javascript-sdk
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
melgarafael/DeskcommCRM#1812 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
prisma/prisma-cli#309 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
gregwebs/pi-quota-dispatcher#26 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
openwatersio/slackwater.xyz#124 ·
Maintainers usually reply within 1 day
-
agent-reported area/browser area/docs documentation good first issue hacktoberfest help wanted P2
Difficulty 1/5 Under an hour Newbie friendliness 90/100
Maintainers usually reply within 2 days