An event-driven orchestrator for Amplifier. Hosts can submit identified user messages and external observations while work runs, receive progress events, and manage background delegation. Without a live runtime, execution returns a normal finite result. Provider-native steering is optional; other providers receive updates at request boundaries.
This is an experimental extraction from Amplifier Converge. It follows the
dependency on loop-streaming's implementation and is not yet a stable community
API. The optional CLI adapter has separate dependencies and packaging under
adapters/cli; importing the core never imports that adapter or either app.
Install into an Amplifier host environment (amplifier-core is a peer dependency):
uv pip install 'git+https://github.com/microsoft/amplifier-module-loop-live'The repository is private during development; normal GitHub authentication is required. The module has no executable. The CLI adapter supplies the terminal experience; Amplifier Converge supplies its own browser and session host.
session:
orchestrator:
module: loop-live
source: git+https://github.com/microsoft/amplifier-module-loop-live@main
config:
background_delegate: trueKeep the module source on main; consuming hosts stage and validate updates and
record installed revisions for rollback. Put this configuration in the host's
root bundle or standalone execution composition, alongside its context module.
Reusable behaviors leave orchestrator selection to that host. The former
behaviors/live.yaml selector has been removed; consumers of that path should
use the configuration above. YAML selects the loop; the application supplies its
live runtime. An ordinary host without that runtime keeps finite execution.
Create amplifier_module_loop_live.runtime.Runtime, register it as the
coordinator capability live.runtime, and own exactly one session.execute()
task. Submit Input values of kind user, steer, service, cancel_job, or
stop. A service must have a distinct source and cannot authorize actions.
Observe runtime events to distinguish acceptance, delivery, tool reports, and
verified outcomes. Stop and await the execution task before cleaning up a session.
Optional capabilities are live.host (a HostAdapter), live.jobs (a private
JobStore), live.checkpoint, and live.attachments.encode. The host owns
approval policy, transport authentication, persistence location, and shutdown.
Runtime history is bounded observation, not a replay log. Saved interrupted jobs
are evidence and are never automatically dispatched again.
If a provider, hook, or host guard cancels an active turn, the live owner settles
through the same cancellation cleanup as Stop. It emits generation.detached
with cancellation unconfirmed and session.closed with cancelled status; it
does not report success or replay completed tools. Hosts must still reconcile
external effects before resuming interrupted work.
JobStore.recover(transcript) compares each saved call and result with the
checkpoint. A returned job whose exact evidence is already present reconciles
silently; the absence of an old display notice is not a recovery event. Missing
calls/results and queued receipts are repaired, conflicting results fail closed,
and newly uncertain outcomes are reported. The returned recovered list contains
jobs with actual restoration/change or newly reported uncertainty, not every
job loaded from the ledger.
Recovery notices retain their stable job/call identities and service provenance.
Their optional metadata.recovery object contains version: 1, job_id,
call_id, status, outcome, and reason (restored_evidence,
changed_evidence, or uncertain_outcome) for host presentation. The private
ledger remembers which result's uncertainty was announced, so compaction that
removes only the notice stays quiet. That fingerprint is not a checkpoint
acknowledgment: restoring an older checkpoint or losing tool evidence still
requires reconciliation, even if the same result was announced earlier.
Live responses carry generation and delivered-input identities, separate from provisional assistant content and native steering acceptance. See the generation event contract and anchored steering before using completion events to resolve a host request or send a notification.
Hosts sharing session storage may supply optional live.activation and
live.park capabilities to release ownership between turns while retaining
mounted modules. See host ownership. These mechanisms
do not choose a storage format or acquire a lock on the host's behalf.
The initial native extension still uses native_bundle_live, steer_live, and
close_live on the selected provider. These are experimental, explicitly
advertised capabilities; selecting a model by name alone does not supply them.
The customized CLI branch adds a separate amplifier live command. See the
CLI adapter installation guide. Its terminal currently
has its own small command set; this does not replace the ordinary CLI REPL.
uv sync --group dev
uv run pytest -q
uv buildCore tests run without the CLI adapter or any provider package. They exercise finite execution, dynamic prompts, queued steering, background delegation with approval hooks, input identity/backpressure, and interruption recovery. The optional adapter and application integration are tested separately by Amplifier Converge's runtime suite. The job ledger currently requires macOS or Linux.
See provenance for the extraction boundary and upstream dependencies.
The mounted loop advertises live.continuation_guard_supported: true. A host may
register async live.continuation_guard() -> bool. The loop calls it immediately
before each automatic goal continuation, including after an awaited goal
evaluator. False clears the goal and returns the last response without submitting
a new model request. Exceptions fail closed. The initial turn for an explicit
input always runs; this guard does not cancel current work, replay input, grant
permissions, or create a second scheduler. Hosts own durable pause/resume state.
Note
This project is not currently accepting external contributions, but we're actively working toward opening this up. We value community input and look forward to collaborating in the future. For now, feel free to fork and experiment!
Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit Contributor License Agreements.
When you submit a pull request, a CLA bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.
This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.
This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft trademarks or logos is subject to and must follow Microsoft's Trademark & Brand Guidelines. Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. Any use of third-party trademarks or logos are subject to those third-party's policies.