Skip to content

feat: close AgentScope D2+D4 thinking/transport gaps - #134

Merged
mindfn merged 5 commits into
mainfrom
codex/agentscope-d2-d4-thinking-transport
Mar 3, 2026
Merged

feat: close AgentScope D2+D4 thinking/transport gaps#134
mindfn merged 5 commits into
mainfrom
codex/agentscope-d2-d4-thinking-transport

Conversation

@mindfn

@mindfn mindfn commented Mar 2, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • implement OpenSpec change agentscope-d2-d4-thinking-transport end-to-end
  • extend transport taxonomy with canonical message/tool_call/tool_result/thinking/error/status and legacy alias canonicalization
  • preserve thinking_content and normalize reasoning_tokens in OpenAI/OpenRouter adapters
  • emit ordered intermediate ReAct transport events (thinking -> tool_call -> tool_result -> message)
  • sync docs: feature evidence, TODO claim ledgers, OpenSpec tasks/proposal/design/specs

Verification

  • openspec validate --changes "agentscope-d2-d4-thinking-transport"
  • pytest -q tests/unit/test_transport_types.py tests/unit/test_transport_adapters.py tests/unit/test_openrouter_adapter.py tests/unit/test_openai_model_adapter.py tests/unit/test_react_agent_gateway_injection.py
  • pytest -q tests/unit/test_transport_channel.py tests/unit/test_base_agent_transport_contract.py tests/unit/test_agent_event_transport_hook.py tests/unit/test_dare_agent_hook_transport_boundary.py tests/unit/test_example_10_agentscope_compat.py
  • pytest -q (528 passed, 12 skipped, 1 warning)

Notes

  • OpenSpec CLI emits PostHog flush DNS errors in this environment (edge.openspec.dev unreachable), but validate/status/apply commands complete successfully and evidence is recorded in docs/features/agentscope-d2-d4-thinking-transport.md.

@mindfn

mindfn commented Mar 2, 2026

Copy link
Copy Markdown
Collaborator Author

@github-copilot please review this PR for regressions, compatibility risks, and missing tests in the D2/D4 transport + thinking changes.

@mindfn

mindfn commented Mar 2, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 39a69ad55a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

"""Extract reasoning token count from provider-specific usage payloads."""
candidates: list[Any] = [
usage.get("reasoning_tokens"),
usage.get("output_tokens_details", {}).get("reasoning")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Read reasoning_tokens from output token details

The new reasoning-token extraction path misses a common OpenAI usage shape: this code reads output_tokens_details.reasoning but not output_tokens_details.reasoning_tokens. When providers only populate output_tokens_details.reasoning_tokens, _extract_usage returns usage without reasoning_tokens, so downstream token accounting/telemetry underreports reasoning cost even though this change set is intended to normalize that field.

Useful? React with 👍 / 👎.

@mindfn

mindfn commented Mar 2, 2026

Copy link
Copy Markdown
Collaborator Author

已根据 review feedback 完成修复并补充回归测试,辛苦再看一轮。@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4bb3f817b7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread dare_framework/agent/react_agent.py Outdated
Comment on lines +141 to +146
await self._emit_transport_success(
transport=transport,
event_type=TransportEventType.MESSAGE.value,
target="prompt",
resp={"output": final_text},
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Remove duplicate terminal transport emission

When ReactAgent is executed through the transport loop (BaseAgent._execute_polled_message), the base class always calls _send_transport_result after execute() returns, so this new explicit message send causes two terminal envelopes for one request (message here plus base result). In interactive channel flows this duplicates user-visible final output and can render the second response as a raw dict payload, which is a regression in transport behavior.

Useful? React with 👍 / 👎.

mindfn added a commit that referenced this pull request Mar 2, 2026
Codex review on PR #134 reported duplicate terminal transport output when ReactAgent runs under BaseAgent's polled-message loop.\n\nRoot cause: ReactAgent emitted a terminal MESSAGE event for final text while BaseAgent always emits a terminal RESULT envelope after execute() returns, causing two terminal payloads for one request in transport-driven flows.\n\nThis change tracks transport-loop execution context in BaseAgent and gates ReactAgent terminal MESSAGE emission in that path. A regression test verifies transport-loop execution now emits THINKING/TOOL_CALL/TOOL_RESULT followed by a single terminal RESULT envelope.
@mindfn

mindfn commented Mar 2, 2026

Copy link
Copy Markdown
Collaborator Author

已处理本轮新增 review 并补测试:\n- 修复 transport loop 下 ReactAgent 终态 MESSAGE 与 BaseAgent RESULT 重复发射问题。\n- 增加回归测试,确保 loop 执行路径只发一个终态 RESULT。\n\n@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b1d31d20cf

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread dare_framework/agent/base_agent.py Outdated
Comment on lines +241 to +245
self._transport_loop_execution = True
try:
result = await self.execute(task, transport=channel)
finally:
self._transport_loop_execution = False

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Track transport-loop state per task instead of globally

_execute_polled_message flips a single agent-wide _transport_loop_execution flag before awaiting execute, and _is_transport_loop_execution treats any non-None transport as loop-driven while that flag is set. If a polled request is in flight and another execute(..., transport=...) runs concurrently on the same agent, the second execution is misclassified as loop execution, so ReactAgent suppresses its terminal message envelope and the caller can miss completion on that transport stream.

Useful? React with 👍 / 👎.

@mindfn

mindfn commented Mar 2, 2026

Copy link
Copy Markdown
Collaborator Author

Processed new actionable review items in this patrol run.\n\nImplemented locally on branch codex/agentscope-d2-d4-thinking-transport:\n- Switched transport-loop execution detection from a shared instance flag to task-local ContextVar state to prevent concurrent execute-path misclassification.\n- Added concurrency regression coverage in test_base_agent_transport_contract.py to ensure loop execution state does not leak across parallel tasks.\n- Re-validated related adapter path (reasoning token extraction already present in this branch, including output_tokens_details.reasoning_tokens).\n\nTargeted verification run:\n- pytest -q tests/unit/test_base_agent_transport_contract.py tests/unit/test_react_agent_gateway_injection.py tests/unit/test_openai_model_adapter.py (15 passed)\n\nPush blocker in this execution environment: outbound git push is denied (ssh: connect to host github.com port 22: Operation not permitted). The commit is ready locally and will be pushed when network policy permits.\n\n@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b1d31d20cf

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread dare_framework/agent/base_agent.py Outdated
Comment on lines +241 to +245
self._transport_loop_execution = True
try:
result = await self.execute(task, transport=channel)
finally:
self._transport_loop_execution = False

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Track loop execution state per task, not per instance

This stores transport-loop state in a shared instance flag, so concurrent executions on the same agent can clobber each other: if two _execute_polled_message calls overlap, the first completion sets the flag to False while the second task is still running, causing _is_transport_loop_execution() to misclassify that in-flight execution. In practice this can emit an extra terminal message event (alongside BaseAgent’s terminal result) or suppress a direct-execute terminal message depending on overlap timing, which makes transport behavior nondeterministic under parallel load.

Useful? React with 👍 / 👎.

mindfn added a commit that referenced this pull request Mar 2, 2026
Address the PR #134 transport-loop concurrency regression where a single\ninstance-level flag marked all concurrent execute() calls as loop-driven.\n\nKey changes:\n- Replace BaseAgent's global  boolean with a\n  task-local ContextVar so loop state does not leak across concurrent tasks.\n- Set/reset the context token inside  to scope the\n  loop marker to that coroutine only.\n- Keep  behavior unchanged for callers while\n  making it concurrency-safe.\n- Add a regression test that runs a polled loop execution and a concurrent\n  direct execute call to verify only the loop task is marked loop-driven.\n\nRationale:\nReactAgent suppresses terminal MESSAGE envelopes when execution is detected as\ntransport-loop initiated. With shared mutable state this suppression could\nincorrectly affect unrelated concurrent direct transport calls.
@mindfn

mindfn commented Mar 2, 2026

Copy link
Copy Markdown
Collaborator Author

Processed the new actionable review comment from this patrol window and confirmed the fix is now on the PR branch.

Pushed:

  • 0420016 to codex/agentscope-d2-d4-thinking-transport

What this addresses:

  • Transport-loop execution state is task-local (ContextVar) instead of shared instance state, preventing concurrent execute-path misclassification.

Targeted verification:

  • /Users/lang/workspace/github/Deterministic-Agent-Runtime-Engine/.venv/bin/pytest -q tests/unit/test_base_agent_transport_contract.py tests/unit/test_react_agent_gateway_injection.py tests/unit/test_openai_model_adapter.py
  • Result: 15 passed.

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 042001632b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +141 to +144
await self._emit_terminal_transport_message(
transport=transport,
output=final_text,
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Emit terminal transport message on all execute exit paths

ReactAgent.execute only emits the terminal message envelope in the if not response.tool_calls branch, but other successful exits (the repeated-tool loop guard and the max-round fallback) return RunResult without any final transport event. In direct execute(..., transport=...) usage this leaves transport consumers with only intermediate tool_call/tool_result events and no completion signal, which can cause clients to wait indefinitely for a terminal message.

Useful? React with 👍 / 👎.

Comment on lines +300 to +304
if isinstance(resp, dict):
request_id = resp.get("request_id")
decision = resp.get("decision")
if isinstance(resp.get("request"), dict):
request_id = resp["request"].get("request_id")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3 Badge Preserve phase text when rendering status payloads

_render_status_output returns immediately for any dictionary resp, so the later resp['phase'] handling is unreachable. As a result, status events shaped like {"resp": {"phase": ...}} are rendered as the generic approval update string instead of the actual phase, dropping useful status detail in stdio output.

Useful? React with 👍 / 👎.

mindfn added a commit that referenced this pull request Mar 2, 2026
Address newly reported review findings on PR #134.\n\nKey changes:\n- Emit terminal MESSAGE envelopes for ReactAgent direct execute() exits when the loop guard triggers or max tool rounds are reached, matching the existing terminal signaling behavior in the normal no-tool-calls path.\n- Adjust status rendering order so structured status payloads with resp.phase render their phase text before approval fallback handling.\n\nRegression coverage:\n- Added ReactAgent transport tests to verify terminal MESSAGE emission for repeated-tool guard exits and max-round exits.\n- Added transport adapter test to verify STATUS events with resp.phase no longer degrade to generic approval text.\n\nVerification:\n- /Users/lang/workspace/github/Deterministic-Agent-Runtime-Engine/.venv/bin/pytest -q tests/unit/test_react_agent_gateway_injection.py tests/unit/test_transport_adapters.py tests/unit/test_base_agent_transport_contract.py
@mindfn

mindfn commented Mar 2, 2026

Copy link
Copy Markdown
Collaborator Author

Processed the new actionable review comments from this patrol window and pushed fixes to the PR branch.

Pushed:

  • 768e90a to codex/agentscope-d2-d4-thinking-transport

What this addresses:

  • ReactAgent now emits a terminal MESSAGE envelope on all direct execute(..., transport=...) success exits, including repeated-tool guard and max-round fallback paths.
  • Structured status payloads with resp.phase now render the phase text before approval fallback in stdio adapters.

Targeted verification:

  • /Users/lang/workspace/github/Deterministic-Agent-Runtime-Engine/.venv/bin/pytest -q tests/unit/test_react_agent_gateway_injection.py tests/unit/test_transport_adapters.py tests/unit/test_base_agent_transport_contract.py
  • Result: 26 passed.

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Swish!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

mindfn added 5 commits March 3, 2026 10:04
Implement the agentscope-d2-d4-thinking-transport OpenSpec slice end-to-end, including transport taxonomy extensions, model reasoning preservation, ReAct intermediate event emission, and evidence sync.

Key changes:

- Extend transport event taxonomy with canonical categories (message/tool_call/tool_result/thinking/error/status) while keeping legacy aliases consumable.

- Add canonicalize_transport_event_type and switch stdio adapter routing to canonical classification without breaking legacy payload handling.

- Preserve provider reasoning in ModelResponse via optional thinking_content and normalize reasoning_tokens in OpenAI/OpenRouter adapter usage metadata.

- Emit canonical thinking/tool_call/tool_result/message events from ReactAgent execute loop and emit structured error payload on tool-call exceptions.

- Add/expand unit tests for transport type canonicalization, adapter reasoning extraction, and ordered ReactAgent intermediate transport events.

- Sync OpenSpec tasks (13/13 complete) and feature evidence documentation for verification traceability.

Verification:

- openspec validate --changes "agentscope-d2-d4-thinking-transport" (pass)

- pytest targeted suite (transport/adapters/react): pass

- pytest impacted regression subset: pass

- pytest -q full suite: 528 passed, 12 skipped, 1 warning
OpenAI-compatible providers may return reasoning token usage under token_usage.output_tokens_details.reasoning_tokens.\n\nThe adapter only read reasoning_tokens at the top level and output_tokens_details.reasoning, which caused reasoning usage to be dropped for providers that follow the newer field name.\n\nThis change adds output_tokens_details.reasoning_tokens as a first-class candidate in the fallback chain and adds a unit test that locks this behavior to prevent regressions.
Codex review on PR #134 reported duplicate terminal transport output when ReactAgent runs under BaseAgent's polled-message loop.\n\nRoot cause: ReactAgent emitted a terminal MESSAGE event for final text while BaseAgent always emits a terminal RESULT envelope after execute() returns, causing two terminal payloads for one request in transport-driven flows.\n\nThis change tracks transport-loop execution context in BaseAgent and gates ReactAgent terminal MESSAGE emission in that path. A regression test verifies transport-loop execution now emits THINKING/TOOL_CALL/TOOL_RESULT followed by a single terminal RESULT envelope.
Address the PR #134 transport-loop concurrency regression where a single\ninstance-level flag marked all concurrent execute() calls as loop-driven.\n\nKey changes:\n- Replace BaseAgent's global  boolean with a\n  task-local ContextVar so loop state does not leak across concurrent tasks.\n- Set/reset the context token inside  to scope the\n  loop marker to that coroutine only.\n- Keep  behavior unchanged for callers while\n  making it concurrency-safe.\n- Add a regression test that runs a polled loop execution and a concurrent\n  direct execute call to verify only the loop task is marked loop-driven.\n\nRationale:\nReactAgent suppresses terminal MESSAGE envelopes when execution is detected as\ntransport-loop initiated. With shared mutable state this suppression could\nincorrectly affect unrelated concurrent direct transport calls.
Address newly reported review findings on PR #134.\n\nKey changes:\n- Emit terminal MESSAGE envelopes for ReactAgent direct execute() exits when the loop guard triggers or max tool rounds are reached, matching the existing terminal signaling behavior in the normal no-tool-calls path.\n- Adjust status rendering order so structured status payloads with resp.phase render their phase text before approval fallback handling.\n\nRegression coverage:\n- Added ReactAgent transport tests to verify terminal MESSAGE emission for repeated-tool guard exits and max-round exits.\n- Added transport adapter test to verify STATUS events with resp.phase no longer degrade to generic approval text.\n\nVerification:\n- /Users/lang/workspace/github/Deterministic-Agent-Runtime-Engine/.venv/bin/pytest -q tests/unit/test_react_agent_gateway_injection.py tests/unit/test_transport_adapters.py tests/unit/test_base_agent_transport_contract.py
@mindfn
mindfn force-pushed the codex/agentscope-d2-d4-thinking-transport branch from 768e90a to da5b7f6 Compare March 3, 2026 02:10
@mindfn
mindfn merged commit 5d1cfb4 into main Mar 3, 2026
8 checks passed
@mindfn
mindfn deleted the codex/agentscope-d2-d4-thinking-transport branch March 3, 2026 02:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant