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]
