[api][plan][runtime] Introduce AGENT resource type and sub-agent invocation API - #938
Open
pltbkd wants to merge 11 commits into
Open
[api][plan][runtime] Introduce AGENT resource type and sub-agent invocation API#938pltbkd wants to merge 11 commits into
pltbkd wants to merge 11 commits into
Conversation
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Design discussion: #909
Linked issue: #1082
Purpose of change
Introduces
AGENTas a first-class resource type and the caller-facing sub-agent invocation API across Java / Python / YAML, per discussion #909.SubagentSetupis the general sub-agent framework. This PR lands the framework and the one way to plug into it today: a customSubagentSetupimplementation. Registering anAgentdirectly as an internal sub-agent is a follow-up addition.Included:
ResourceType.AGENT; register viaaddResource(name, AGENT, setup)and via YAMLsubagents:.SubagentSetup(single caller-facing surface) +SubagentFuture/SubagentFutures(handles) +SubagentResult(outcome). Implementations capture their failures into a result instead of throwing, so callers checkisSuccess();getResult(Class)re-binds the payload identically on a first execution and on a replay.submit(ctx, prompt)is the preferred form and returns a handle; passing asessionIdcontinues an earlier conversation. Python mirrors the surface asawait setup.submit(...)thenawait future.(sessionId, callId)identity, framework-assigned from the caller-side facts of the action execution, so failover replay reuses the persisted outcome instead of re-invoking.status_poll_interval_millisdescriptor argument).TaskLifecycleListener/ComponentExecutionListenerreplacetrace/ExecutionEventLogger+ExecutionEventSink, andResourceCache.eagerMaterializeregisters setups of either language while the operator opens (Python-owned ones reach Java as a non-owningPythonRuntimeResourcehandle).Evolved from the #909 proposal during review:
SubagentResult(renamed fromResult) carries the failure's type and message instead of a liveException, so it survives durable persistence; the full stack trace is logged rather than persisted, keeping the payload bounded.Subagentcaller interface was dropped and merged intoSubagentSetup, to avoid a second public type with "agent" in the name meaning something other than the authored, event-drivenAgent.BaseSubagentCallablewas replaced by the runtime setup base plus the two execution modes, which wire the reconciler by default instead of leaving it to each implementation.(sessionId, callId); on the Python side durable execution gained explicit id keying, since deriving the id from the callable alone collapsed every sub-agent call onto one key.subagents:is treated as first-class API (schema + loader), not doc-only.Notes
Agentdirectly as anAGENTresource, compiled into a scoped child plan, and its isolated execution).sessionIdmay be passed to continue an earlier conversation, but whether that works across action executions is up to the implementation: the framework does not carry the per-session ordinal across action tasks, because branch and diamond structures make the acquisition order unreproducible.Tests
SubagentSetup+ YAML descriptor), typed result on first execution and on replay, deterministic id assignment and its namespace digest, the per-task pending-call registry, task lifecycle notification including replay pairing, eager materialization in both languages, and both execution modes (deferred submit / cancel / group resolve, async POST-probe-fetch with reconcile paths and the configured poll interval).SubagentResult.ExternalAgentSubagentSetupTestdrives both modes against an external agent service over real HTTP — success, remote failure, the two resolved as one group, and the reconcile paths across a crash window (the POST landed, and the POST was lost). An in-process stub service runs by default and needs nothing installed;-Dexternal.agent.url=...points the same suite at a real deployment, which is how it was also verified against a demo service.API
Additive public API, kept semantically aligned across Java / Python / YAML:
ResourceType.AGENT,SubagentSetup,SubagentFuture,SubagentFutures,SubagentResult, and the YAMLsubagents:block.No breaking changes to existing APIs. Runtime-internal only: the tracing hooks became the
TaskLifecycleListener/ComponentExecutionListenerextension points.Documentation
doc-neededbut deferred: add once the internal sub-agent lands and the API stabilizesdoc-not-neededdoc-included