feat(flows): support runtime agent fan-out - #34
Open
antoinegg1 wants to merge 2 commits into
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.
Background
Humanize flows traditionally declare a fixed agent tuple before a run starts. That is correct for validating backend capabilities and preparing the run, but it does not cover workflows whose fan-out is only known after an initial planning/triage turn. For example, a triage agent may select a variable number of specialist departments, and the workflow should then run one independent specialist agent per selected department.
Agent.clone()and asynchronous turns already provide the low-level building blocks, but a clone created afterRunner.run()starts was previously outside the run lifecycle: it was absent fromRunner.agents, cycle records, TUI monitoring, andRunner.stop(). This change adds the missing lifecycle registration without changing the existing static flow contract or backend/session implementations.Implementation
hmz.flows.spawn(template, names)as the opt-in public API. It validates non-empty, unique names, clones the template configuration/skills, and returns the new agents in input order.Cycle. Registration is atomic across the whole root run, including called flows, so name collisions cannot partially admit a fan-out.spawnedjournal event with parent and agent configuration.cycle.read()reconstructs these agents alongside the declared agents.Subcycles. A child created by a called flow is recorded in its own flow record and in the root run inventory, and is stopped with the rest of the run.Runnerwith a dynamicagentssnapshot, an agent-join watcher, and run-wide stop handling. A stop request racing withspawn()stops the newly admitted agent before it can take a turn. The stop flag is reset after a run so aRunnercan be reused.Run.stop()delegates to the runner registry.spawn().Runtime Behavior
A typical run now behaves as follows:
Runnerperforms the normal pre-run validation and starts one root cycle containing the declared agents.spawn()validates all requested names and creates independent clones. The original template is not reconfigured.spawn()returns.Runner.agents, SDKRun.agents, the TUI, and cycle tracing can see the new agents before their first turn.asyncio.gather()or another scheduling policy. Each clone has its own sessions, identity, configuration, workspace selection, and trace entries.spawnedandopenedrecords, while old cycles withoutspawnedevents remain readable.spawn()outside a running cycle still works as a named group ofclone()calls; in that case the caller owns cleanup because there is no Humanize run to manage them.Compatibility and Scope
This is an additive change. Existing flows that do not call
spawn()retain their previous behavior and fixed startup validation. No Flowverse changes are included in this PR; the companion reference flow remains local until the core API is reviewed and merged.Validation
PYTHONPATH=src /usr/local/bin/pytest -c /tmp/hmz-pytest.ini tests/test_dynamic_agents.py -q-> 7 passed/usr/bin/python3cannot import localhmz)