-
Notifications
You must be signed in to change notification settings - Fork 43
feat(simulate): platform scenarios + LiveKit SIP transport + provider acceptance flows #55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
azain-commits
merged 43 commits into
release/v1-agent-learning-kit-dev
from
feat/platform-scenarios-livekit-sip
Aug 18, 2026
Merged
Changes from all commits
Commits
Show all changes
43 commits
Select commit
Hold shift + click to select a range
ee69932
feat(alk): platform-generated scenarios + canonical voice prompts + L…
azain-commits 67033fa
feat(alk): wire scenario generation into CLI + Studio downloader upgr…
azain-commits c063404
feat(sim): stage-0/5 protocol layer, evidence sources, matrix runner,…
azain-commits e16933a
fix(sim): repair LiveKit SIP transport, wire Vapi originator, tighten…
azain-commits 3cf8c8f
feat(simulate): add direct voice SDK workflow
azain-commits 963a399
feat(simulate): separate voice target from FutureAGI LiveKit runtime …
azain-commits 35d6525
fix(studio): omit scenario-only agent flag
azain-commits d2b1420
feat(simulate): complete provider acceptance flows
azain-commits b53e4a7
feat(simulate): pool-aware LiveKit engine + provider acceptance harde…
azain-commits 1999a1e
fix issues on livekit engine, add support for posting simulate data t…
azain-commits cf3f3eb
feat(simulate): real platform submission in FutureAGIResultSink
azain-commits 6484b2b
feat(simulate): submit target-agent token usage + cost to platform
azain-commits c239ace
fix(evals): exclude non-applicable metrics from agent-report aggregate
azain-commits e0d9e2e
feat(evals): live litellm/Vertex provider for eval + optimize-eval su…
azain-commits ed86c24
fix(opt): configurable task_model, drop hardcoded gpt-4o-mini/gpt-5-mini
azain-commits 01f6904
feat(evals,opt): wire platform evals + all optimizers into agent-learn
azain-commits bcd1a76
fix(simulate): tool-call fidelity + per-turn latency in chat runs
azain-commits c695347
refactor(simulate): gym-model runtime — adapter registries + world_ki…
azain-commits d1208ce
feat(simulate): SDK hosted-runner package (child entrypoint + job + t…
azain-commits e573c93
feat(simulate): per-persona TTS voice selection
azain-commits 3db32eb
fix(simulate): send internal Bearer secret alongside FI keys on submit
azain-commits ee26069
fix(simulate): enable preemptive generation to cut voice turn latency
azain-commits 60a924c
feat(voice): run a scenario's cases concurrently, bounded by agent ca…
azain-commits 3f1413d
feat(simulate): stream hosted voice cases to the platform as each fin…
azain-commits c95629f
fix(voice): run sims to natural end + stop transcript role reversal
azain-commits d13f8c2
fix(livekit): send empty dispatch metadata to external target agents …
azain-commits b93f2c9
fix(livekit): capture target-agent turns so webrtc sims run a real co…
azain-commits 1fc2a40
fix(simulate): drive agent_first conversations from the target greeting
azain-commits 0f4b5de
Revert "fix(simulate): drive agent_first conversations from the targe…
azain-commits fa87079
fix(simulate): capture the target's opening greeting in agent_first
azain-commits 7f080e6
feat(simulate): stereo voice recording (customer left / assistant right)
azain-commits 5de580c
feat(simulate): streaming Gemini TTS for the simulator voice (multili…
azain-commits bfc6caf
fix(simulate): capture final target turn, truncate interrupted turns,…
azain-commits 34711b7
fix(simulate): commit target turns directly so the trailing closing i…
azain-commits 0d75d91
fix(simulate): capture target closing via independent stream, not the…
azain-commits 82f23a8
fix(simulate): also wait for the simulator's own final turn before sn…
azain-commits f429e1b
fix(simulate): delete the room on conversation end so the call actual…
azain-commits ecd0153
feat(simulate): per-case ONGOING status for hosted sims
azain-commits 260e366
fix(simulate): align SDK voice results and recordings
azain-commits 32101a1
fix(results): allow internal service authentication
azain-commits 74f1c28
docs(simulate): add Spec + Runner quickstart, drop "gym" branding
azain-commits df2d379
fix(simulate): repair the livekit engine test suite + gate it in CI
azain-commits c719ffd
fix(simulate): make fi.simulate importable without the livekit extra
azain-commits File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| name: SDK smoke | ||
|
|
||
| on: | ||
| push: | ||
| pull_request: | ||
|
|
||
| jobs: | ||
| clean-install: | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 15 | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: actions/setup-python@v5 | ||
| with: | ||
| python-version: "3.12" | ||
| cache: pip | ||
| - name: Install package | ||
| run: python -m pip install . | ||
| - name: Run doctor | ||
| run: agent-learn doctor --quiet | ||
| - name: Run local text simulation | ||
| env: | ||
| AGENT_LEARNING_RUN_EXAMPLE_KEY: smoke | ||
| run: >- | ||
| agent-learn simulation run examples/run_manifest.json | ||
| --output smoke-report.json --quiet | ||
| - name: Verify simulation report | ||
| run: >- | ||
| python -c "import json, pathlib; | ||
| report=json.loads(pathlib.Path('smoke-report.json').read_text()); | ||
| assert report['status'] == 'ran' and report['report']['results']" | ||
| - name: Install test dependencies | ||
| run: python -m pip install '.[livekit]' pytest pytest-asyncio | ||
| - name: Run engine + dispatch + acceptance tests | ||
| # Scoped to the suites this PR adds/relies on. The broader tests/ tree has | ||
| # pre-existing failures unrelated to the voice engine (CLI golden-path, | ||
| # init presets, plus test_config_and_facades hangs) — track those | ||
| # separately so this gate stays green and meaningful. | ||
| run: >- | ||
| python -m pytest -q | ||
| tests/runtime/test_livekit_engine.py | ||
| tests/runtime/test_manifest_engine_dispatch.py | ||
| tests/test_acceptance_regressions.py | ||
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
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
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
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
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,134 @@ | ||
| --- | ||
| kind: agent-learning.docs-page.v1 | ||
| track: simulate | ||
| objective: behavior | ||
| stage: simulate | ||
| backing: | ||
| - examples/sdk_spec_runner_quickstart.py | ||
| artifact_kinds: [] | ||
| commands: | ||
| - python examples/sdk_spec_runner_quickstart.py artifacts/spec-and-runner.json | ||
| postcondition: python -c "import json; p=json.load(open('artifacts/spec-and-runner.json')); assert 'COMPLETED' in p['status'], p['status']; print('ok')" | ||
| claims: [] | ||
| doctor_checks: | ||
| - missing_engine_modules | ||
| - public_boundary_passed | ||
| opt_in_lane: false | ||
| --- | ||
|
|
||
| # The Simulation Spine — One Spec, One Runner | ||
|
|
||
| > **Twin:** [`examples/sdk_spec_runner_quickstart.py`](../../examples/sdk_spec_runner_quickstart.py) | ||
| > · offline, no credentials. | ||
| > For the full end-to-end tour (real LLM, voice, platform submit, custom | ||
| > worlds) see [`examples/agent_learning_sdk_demo_v2.ipynb`](../../examples/agent_learning_sdk_demo_v2.ipynb). | ||
|
|
||
| Under the manifest and CLI surfaces, every simulation — chat, voice, or a | ||
| custom world — runs through **one** spine: a frozen `SimulationSpec` fed to | ||
| **one** `SimulationRunner`. Providers, environments, and agent kinds are | ||
| registry entries, not hardcoded branches. This page runs the smallest version of | ||
| that spine directly, so the moving parts are visible. | ||
|
|
||
| | Piece | In the SDK | You supply | | ||
| | --- | --- | --- | | ||
| | **Environment** | a registered plugin (`chat`, `voice`, or your own) that owns the world + action space | pick one, or `@register_environment` your own | | ||
| | **Target** | an ActorSource (`system_prompt` \| callable \| `factory` \| `http` \| `framework`), or any object with `.call()` | drop in your agent | | ||
| | **Scenario** | personas + situations + desired outcomes | describe the test | | ||
| | **Contract** | a frozen `SimulationSpec` tying the three together | declarative, secret-free | | ||
| | **Runner** | one `SimulationRunner` — same spine for chat and voice | `.run(spec, target=...)` | | ||
|
|
||
| ## 1. Install and check | ||
|
|
||
| ```bash | ||
| git clone https://github.com/future-agi/agent-learning-kit | ||
| cd agent-learning-kit | ||
| uv sync # or: pip install -e . | ||
| uv run agent-learn doctor # status: passed | ||
| ``` | ||
|
|
||
| ## 2. Run the smallest simulation | ||
|
|
||
| A synthetic user drives a conversation against a plain `.call()` target through | ||
| the runner. No API key, no network. | ||
|
|
||
| ```python | ||
| import asyncio | ||
| import fi.alk.simulate as S | ||
| from fi.simulate.agent.wrapper import AgentInput, AgentResponse | ||
|
|
||
|
|
||
| class EchoAgent: | ||
| async def call(self, agent_input: AgentInput) -> AgentResponse: | ||
| last = agent_input.messages[-1]["content"] if agent_input.messages else "hi" | ||
| return AgentResponse(content=f"You said: {last}. How can I help further?") | ||
|
|
||
|
|
||
| async def main(): | ||
| print(sorted(S.environment_registry.names())) # ['chat', 'voice'] | ||
| spec = S.SimulationSpec( | ||
| run_id="spec_runner_quickstart", | ||
| environment=S.EnvironmentSpec( | ||
| adapter=S.EnvironmentAdapters.CHAT, | ||
| world_kind=S.WorldKinds.CONVERSATION, | ||
| config={"max_turns": 3, "min_turns": 1}, | ||
| ), | ||
| target=S.AgentEndpointSpec(adapter=S.TargetAdapters.CALLABLE), | ||
| simulator=S.SimulatorPolicySpec(adapter=S.SimulatorAdapters.SYNTHETIC_USER), | ||
| scenario=S.Scenario(name="late-delivery", dataset=[ | ||
| S.Persona(persona={"name": "Morgan", "role": "customer"}, | ||
| situation="A delivery is 3 days late; ask for status and ETA.", | ||
| outcome="Get a clear status and a concrete next step.")]), | ||
| ) | ||
| report = await S.SimulationRunner().run(spec, target=EchoAgent()) | ||
| print(report.status) | ||
| print(report.test_cases[0].result.transcript) | ||
|
|
||
|
|
||
| asyncio.run(main()) | ||
| ``` | ||
|
|
||
| The backing twin is the same run, writing the finished report to a path: | ||
|
|
||
| ```bash | ||
| python examples/sdk_spec_runner_quickstart.py artifacts/spec-and-runner.json | ||
| python -c "import json; p=json.load(open('artifacts/spec-and-runner.json')); assert 'COMPLETED' in p['status']; print('ok')" | ||
| ``` | ||
|
|
||
| Every adapter slot accepts the enum (`S.EnvironmentAdapters.CHAT`) **or** the | ||
| plain string it equals (`"chat"`) — same `spec_hash`. Enums give you | ||
| autocomplete and typo-safety for the built-ins; custom registered names stay | ||
| plain strings. | ||
|
|
||
| ## 3. Drop in your own agent | ||
|
|
||
| `EchoAgent` was passed straight to the runner. Every other way you'd hand the | ||
| kit an agent is an ActorSource resolved through one registry — you declare what | ||
| you have, you never edit the engine: | ||
|
|
||
| ```python | ||
| S.get_profile("system_prompt").resolve_target({"system_prompt": "...", "model": "gpt-4o"}) | ||
| S.get_profile("factory").resolve_target({"target": "mypkg.agents:Support", "factory": True}) | ||
| S.get_profile("http").resolve_target({"url": "https://my-agent/turn"}) | ||
| S.get_profile("framework").resolve_target({"target": "mypkg:graph"}) # LangGraph / CrewAI / ... | ||
| ``` | ||
|
|
||
| Code-loading kinds (`factory`, `import_object`, `framework`, callable) carry | ||
| `runs_caller_code == True` and are deny-by-default in hosted runs — locally they | ||
| resolve in-process, hosted they route through the sandbox. `http` and | ||
| `system_prompt` are the hosted-safe kinds. Check with | ||
| `S.get_profile("http").runs_caller_code`. | ||
|
|
||
| ## 4. Where to go next | ||
|
|
||
| | Task | Spec + Runner API | | ||
| | --- | --- | | ||
| | Real-LLM chat | `SimulationRunner().run(spec, target=your_llm_object)` | | ||
| | Voice (Vapi / Retell / WebRTC) | `SimulationRunner().run(voice_spec)` — see the v2 notebook §7 | | ||
| | Score a run | `evaluate_agent_report(report.to_legacy())` | | ||
| | Register your own world | `@register_environment("name")` | | ||
| | Submit to the platform | `result_sink=FutureAGIResultSink(...)` | | ||
|
|
||
| - Full runnable tour: [`examples/agent_learning_sdk_demo_v2.ipynb`](../../examples/agent_learning_sdk_demo_v2.ipynb). | ||
| - The older manifest/CLI front door: [`first-run.md`](first-run.md) — same | ||
| concepts, assembled into a `SimulationSpec` underneath. | ||
| - Frameworks as targets: [`simulate-any-framework.md`](simulate-any-framework.md). |
Oops, something went wrong.
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The workflow doesn't run the tests this PR adds.
Credit first: this file is new in this PR, so it takes the repo from no CI to some CI. That's the right direction.
But as written it installs the package, runs
agent-learn doctor, and executes one local text simulation. Nopytest, no lint. So roughly 3,000 lines of new tests —test_livekit_engine.py(1,915),test_manifest_engine_dispatch.py(521),test_acceptance_regressions.py(490) — never execute in CI.That's the mechanism behind the five failures above surviving six commits: nothing was watching.
A step like:
would close it. Two caveats from running the suite locally:
tests/test_config_and_facades.pyhangs (>3 min, also on the base branch — pre-existing, worth an--ignoreor a timeout), andtests/test_phase7_persona_studio.pyhas 2 network-dependent failures that also reproduce on base. Neither is introduced here, but both need handling before apytestgate goes green.