yunfengzhou-hub opened a new issue, #1137:
URL: https://github.com/apache/flink-agents/issues/1137

   ### Search before asking
   
   - [x] I searched in the 
[issues](https://github.com/apache/flink-agents/issues) and found nothing 
similar.
   
   ### Description
   
   ### Motivation
   
   Since #938 / #1082, an in-process ("deferred") sub-agent is authored by 
hand-writing a `DeferredSubagentSetup` subclass implementing `prepare()`. That 
setup is a single deferred callable with no action loop of its own, so reusing 
an existing, fully-formed `Agent` — with its own actions, resources, and event 
loop — as a sub-agent means re-expressing it as a deferred setup. This is 
boilerplate-heavy and does not compose (a sub-agent cannot itself own 
sub-agents).
   
   ### Proposed feature
   
   Allow a plain child `Agent` instance to be registered directly as an `AGENT` 
resource, and have the framework compile it into an in-process **internal 
sub-agent** that runs its own action loop. The caller resolves it like any 
other resource and awaits its accumulated `Result`:
   
   ```python
   class RootAgent(Agent):
       @action(InputEvent.EVENT_TYPE)
       @staticmethod
       async def orchestrate(event: Event, ctx: RunnerContext) -> None:
           prompt = InputEvent.from_event(event).input
           child = ctx.get_resource("reviewer", ResourceType.AGENT)
           future = await child.submit(ctx, prompt)   # no-id form
           result = await future
           ctx.send_event(OutputEvent(output=result.result[0]))
   
   root = RootAgent()
   # Register a plain child Agent as an AGENT resource — no hand-written setup:
   root.add_resource("reviewer", ResourceType.AGENT, EchoChildAgent())
   ```
   
   - **Identical registration.** Declared only via `addResource(name, 
ResourceType.AGENT, instance)` or the YAML `subagents:` block — no new 
annotation, consistent with #909.
   - **Isolation** (umbrella requirement). The child runs in its own 
`SubagentScope`: a scope-aware `RunnerContextImpl` (resolved via 
`getActiveScopePlanJson`) and an `IsolatedCachedMemoryStore`, so the child's 
`send_event`/`get_resource` and memory do not leak into the parent.
   - **Durability** (umbrella requirement). The no-id form `submit(ctx, 
prompt)` is the public, preferred API: the framework deterministically derives 
the `(session_id, call_id)` pair from the executing action task and replays it 
identically after a failover; call events are replayed for recovery. The 
explicit-id form stays reserved for internal use.
   - **Nesting.** A child may itself register and await a grandchild.
   - **Failures surface as data** through the caller's `Result` 
(`success=False`, `error_message`) instead of failing the job.
   - **Cross-language** (touches umbrella step 6). A Python child agent 
compiles to a child plan that a Java caller — or a Python caller through the 
embedded interpreter — can drive.
   
   ### Proposed solution
   
   Implemented on a branch; PR to follow.
   
   - **Plan.** `AgentPlan` distinguishes three mutually exclusive 
`AGENT`-resource cases — `SubagentSetup` (deferred), `ResourceDescriptor` 
(YAML), and `instance of Agent`. Only the third routes to a new 
`InternalSubagentCompilationHelper`, compiling the child's plan into an 
`InternalSubagentProvider` / `InternalSubagentSetup`. A Python-compiled child 
plan is serialized via `PythonSerializableResourceProvider` and materialized 
reflectively on the Java side.
   - **Runtime.** The caller's action dispatches an `InternalSubagentCallEvent` 
on the mailbox thread; the child's actions run scope-aware with isolated 
memory; the child's output events accumulate into the caller's `Result`; call 
events are replayed for checkpoint/failover recovery.
   - **Cross-language no-id support.** `ActionExecutionOperator` registers the 
`PythonTaskLifecycleListener` when the root plan declares a Python-compiled 
sub-agent (`hasPythonCompiledSubagent()`), so `notify_action_prepared` reaches 
the Python caller; `FlinkRunnerContext` captures the prepared task's namespace 
and replays it onto the lazily-materialized handle (`adopt_prepared_namespace`) 
so a no-id `submit` can mint deterministic `(session_id, call_id)`.
   
   Note: the JDK 21 continuation path is only needed for a **Java** caller 
action to await in-process; a **Python** caller releases the mailbox by 
yielding at `await`.
   
   ### Scope
   
   Components: `[api]`, `[plan]`, `[runtime]`, `[python]`.
   
   ### Are you willing to submit a PR?
   
   - [x] I'm willing to submit a PR!


-- 
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