zzwqqq opened a new pull request, #1344:
URL: https://github.com/apache/flink-agents/pull/1344

   <!-- Suggested title: [runtime][java][python] Preserve internal subagent 
framework faults through tool calls and the Python bridge -->
   Linked issue: #1322 (second item only)
   
   ### Purpose of change
   
   Preserve framework faults from internal subagent calls, including their 
original causes. These faults currently become failed tool responses and can 
then be masked by an unresolved-handle error.
   
   This PR addresses the second item only. Group cleanup, ordinary 
future/gather behavior, and model routing/retry policies are unchanged.
   
   #### Runtime flow
   
   Internal call operations and ActionState writes mark framework faults with 
`UncapturableException`. `FunctionTool`, `ToolCallAction`, subgraph execution, 
and durable recording propagate that marker through wrapped causes. The Python 
bridge carries the Java Throwable or Python error details back to Java before 
result conversion.
   
   #### Key decisions
   
   `UncapturableException` moves to `plan.exceptions` so plan and runtime share 
the classification. Python uses an internal counterpart and a per-call return 
envelope because Pemja otherwise loses the type and cause.
   
   ### Behavioral Semantics
   
   #### Interaction decisions
   
   | Failure / path | Result |
   | --- | --- |
   | Ordinary child failure, Java or Python | Failed `SubagentResult` |
   | Marked tool/subagent fault, direct or nested, serial or parallel dispatch 
| Propagates with its cause |
   | Wait failure, even if the child also failed | Propagates the wait failure |
   | Ordinary / marked tool metadata failure | Existing fallback / propagate 
the fault |
   | Marked durable call or completion fault | No terminal failure recorded; 
earlier completed work remains available |
   | Java-origin / Python-origin fault crossing the bridge | Original Java 
Throwable / Python type, message and traceback |
   
   #### Behavioral contracts
   
   Nested calls retain the framework cause. Recovery can reuse completed child 
work and retry unfinished work after the storage fault is removed. Ordinary 
tool failures keep their existing handling, and user return values cannot be 
mistaken for bridge faults.
   
   #### Failure behavior
   
   Marked faults fail the Action through the existing runtime path; no retry 
policy is added. Cancellation, interruption and fatal errors retain their 
handling. Invalid bridge envelopes raise framework faults. Interpreter close 
still runs if dispatcher cleanup fails, retaining the first failure and 
suppressing a later close failure. User catch blocks can still handle 
exceptions.
   
   ### Tests
   
   | Behavior | Coverage |
   | --- | --- |
   | Framework faults escape tool-response conversion | `FunctionToolTest`, 
`ToolCallActionSubagentTest`; Python `test_tool_call_action.py` and 
`test_subagent_await_cleanup.py` |
   | Nested calls retain the cause; ordinary child failures remain results | 
`InternalSubagentFrameworkFaultTest`, `FrameworkFaultBridgeTest` |
   | Wait failures remain distinct from child failures | 
`SubgraphInvocationTest` |
   | Framework faults are not recorded as terminal failures; recovery reuses 
completed work | Java/Python durable tests and the operator snapshot/restore 
case |
   | The Python bridge preserves causes, diagnostics and ordinary return values 
| `FrameworkFaultBridgeTest` |
   | Invalid envelopes fail; interpreter close survives cleanup errors | 
`PythonFaultBridgeTest` |
   
   Not verified: distributed-cluster fault injection, external model-service 
E2E, or Python 3.10/3.12. Python-child operator tests require JDK 21; the 
existing JDK 17 restriction is unchanged.
   
   <details>
   <summary>Validation details</summary>
   
   | Local check (Flink 2.3.0) | Result |
   | --- | --- |
   | Java UT, JDK 21 | 3,741 tests, 129 skipped, no failures/errors |
   | Python UT, Python 3.11 | 2,928 passed, 16 skipped, 201 deselected |
   | Native Pemja/MiniCluster tests, JDK 21, no external model service | 11 
passed |
   | New Java core regressions, JDK 17 | 19 passed |
   | Spotless, Ruff, Apache RAT, `git diff --check` | Passed |
   
   Java: `env -u OPENAI_API_KEY ./tools/ut.sh -j`, with live OpenAI tests 
skipped. Python: pytest with `not e2e_tests` and `not integration`, matching 
the `tools/ut.sh -p` selection.
   
   Classification uses explicit causes. The bridge envelope belongs to one call 
and never enters the journal; ordinary Python exceptions retain Pemja's 
exception path. Attribute lookup and close-time cleanup manage the dispatcher's 
references.
   
   </details>
   
   ### API
   
   No user-facing API signatures or YAML options change. The internal 
`UncapturableException` moves from `runtime.operator.parallel` to 
`plan.exceptions`; code importing it must update imports and recompile.
   
   ### Documentation
   
   - [ ] `doc-needed`
   - [ ] `doc-not-needed`
   - [x] `doc-included`
   
   ### Was this patch authored or co-authored using generative AI tooling?
   
   - [x] Yes
   - [ ] No
   
   Generated-by: Codex 0.164 (gpt-6)


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to