Skip to content

[AAASM-1227] ✨ (runtime): Add SDK runtime auto-detection and lifecycle (F115)#48

Merged
Chisanan232 merged 10 commits into
masterfrom
v0.0.1/AAASM-1227/feat/runtime_lifecycle
May 21, 2026
Merged

[AAASM-1227] ✨ (runtime): Add SDK runtime auto-detection and lifecycle (F115)#48
Chisanan232 merged 10 commits into
masterfrom
v0.0.1/AAASM-1227/feat/runtime_lifecycle

Conversation

@Chisanan232
Copy link
Copy Markdown
Contributor

Description

Adds agent_assembly/runtime.py, a new submodule that implements the F115 runtime lifecycle: locate the aasm Rust sidecar, probe whether it's already running, start it if not, and report a clear install hint when no binary is found. The new orchestrator is exposed as agent_assembly.runtime.init_assembly(agent_id) and is not re-exported from the top-level package — the existing gateway-based agent_assembly.init_assembly(gateway_url, api_key, ...) keeps its meaning.

Type of Change

  • ✨ New feature
  • 🔧 Bug fix
  • ♻️ Refactoring
  • 🍀 Performance improvement
  • 📚 Documentation update
  • 🚀 Release

Breaking Changes

  • No
  • Yes (please describe below)

The new module is additive. Nothing under agent_assembly or any framework adapter is touched.

Related Issues

  • Related JIRA ticket: AAASM-1227 (Story AAASM-1205 / Epic AAASM-1199)
  • Related GitHub issues: N/A
  • Related PRs (sibling sub-tasks under AAASM-1205): node-sdk AAASM-1228, go-sdk AAASM-1229 — to be opened after this lands.

Testing

Tests for runtime.py are intentionally deferred to AAASM-1230 (cross-SDK test sub-task) per the story decomposition.

  • Unit tests added/updated
  • Integration tests added/updated
  • Manual testing performed
  • No tests required (explain why)

Local verification:

  • ruff check agent_assembly/runtime.py → clean
  • ruff format --check agent_assembly/runtime.py → clean
  • mypy --ignore-missing-imports agent_assembly/runtime.py → 0 errors attributable to this file (the 10 errors in types.py, client/gateway.py, core/assembly.py are pre-existing on master HEAD 6abb6c3).
  • pre-commit run --files agent_assembly/runtime.py → all hooks pass except the project-wide mypy step (pre-existing red).

Checklist

  • Code follows project style guidelines
  • Self-review completed
  • Comments added for complex logic
  • Documentation updated if needed
  • All tests passing

Commit breakdown (5 commits, each ≈ one logical unit)

# Subject
1 ✨ (runtime): Add agent_assembly/runtime.py skeleton with F115 constants
2 ✨ (runtime): Add find_aasm_binary() resolver across the 5 install paths
3 ✨ (runtime): Add is_running() local TCP liveness probe
4 ✨ (runtime): Add start_runtime() detached sidecar spawn
5 ✨ (runtime): Add init_assembly() lifecycle orchestrator

What init_assembly() does

init_assembly(agent_id=None, *, port=DEFAULT_PORT)
  1. if is_running(port): return                  # idempotent re-init
  2. binary = find_aasm_binary()                  # 5 search paths
     if binary is None: raise RuntimeError(INSTALL_HINT)
  3. start_runtime(binary, port=port)             # detached subprocess

Binary search order

Step Location Covers install method
1 $PATH (via shutil.which) brew install, cargo install
2 ~/.local/bin/aasm curl | sh
3 agent_assembly/bin/aasm (wheel-bundled) pip install agent-assembly-python[runtime]
4 /usr/local/bin/aasm Docker base image

Module-level constants and the install-hint message that the four lifecycle
functions in subsequent commits will share. The orchestrator stays inside
the runtime submodule to avoid collision with the existing gateway-based
agent_assembly.init_assembly.

Refs AAASM-1227 / AAASM-1205.
Resolves the aasm binary in this order: $PATH → ~/.local/bin/aasm →
agent_assembly/bin/aasm (wheel-bundled) → /usr/local/bin/aasm (Docker
base image). Each non-PATH candidate must exist and be executable to
match. Returns Path | None; callers convert None into the install hint.

Refs AAASM-1227.
Attempts a 100 ms TCP connect to 127.0.0.1:DEFAULT_PORT and returns the
boolean outcome. Any OSError (connection refused, timeout, unreachable)
is treated as no sidecar — the lifecycle orchestrator uses this to skip
start_runtime() when the sidecar is already up (idempotent re-init).

Refs AAASM-1227.
Spawns `aasm serve --port <port>` with stdin closed, stdout+stderr
appended to .aasm-runtime.log under log_dir (default: CWD), and
start_new_session=True so the child detaches from this process's
controlling terminal. Returns the Popen handle; the caller does not
block on the child.

Refs AAASM-1227.
Implements the F115 four-step lifecycle: probe → resolve binary → spawn.
Returns early when is_running() reports a live sidecar (idempotent
re-init), raises RuntimeError with INSTALL_HINT when find_aasm_binary()
returns None. agent_id is accepted per the AAASM-1227 signature but is
not consumed at the lifecycle layer; the existing gateway-aware
agent_assembly.init_assembly handles register-and-connect once the
sidecar is reachable.

Closes AAASM-1227.
@codecov
Copy link
Copy Markdown

codecov Bot commented May 21, 2026

Codecov Report

❌ Patch coverage is 76.19048% with 10 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
agent_assembly/runtime.py 76.19% 10 Missing ⚠️

📢 Thoughts on this report? Let us know!

Module docstring + imports + the agent_assembly.runtime under-test
import. Test functions land in subsequent commits — one per AC
scenario (binary-in-PATH, binary-bundled, binary-not-found,
already-running).

Refs AAASM-1227 / AAASM-1230.
Writes an executable aasm shim into a tmp_path, points PATH at it via
monkeypatch, and asserts find_aasm_binary returns that exact path.
This is the primary install-via-Homebrew / cargo install / curl
installer code path.

Also adds the _make_fake_aasm helper that the next two tests will
reuse.

Refs AAASM-1227 / AAASM-1230.
Empties $PATH, points USER_LOCAL_BIN + DOCKER_BASE_BIN at non-existent
dirs, points WHEEL_BUNDLED_BIN at a tmp dir containing the fake aasm
shim, and asserts find_aasm_binary returns the bundled path. Covers
the `pip install agent-assembly-python[runtime]` wheel scenario from
the AAASM-1205 install matrix.

Refs AAASM-1227 / AAASM-1230.
Sets every search location to a non-existent directory and forces
is_running to return False, then asserts init_assembly raises
RuntimeError whose message is exactly runtime.INSTALL_HINT — i.e.
the full pip / brew / curl install copy-paste shown to end users.

Refs AAASM-1227 / AAASM-1230.
Patches is_running to True and asserts neither find_aasm_binary nor
start_runtime is called — the orchestrator's structural guarantee
that repeated init_assembly invocations do not spawn duplicate
sidecars. Closes the 4th scenario from the AAASM-1230 AC checklist
for the Python SDK.

Also drops the unused os/subprocess imports the skeleton speculatively
included.

Refs AAASM-1227 / AAASM-1230.
@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
76.2% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

@Chisanan232 Chisanan232 merged commit 0eb43a1 into master May 21, 2026
22 of 24 checks passed
@Chisanan232 Chisanan232 deleted the v0.0.1/AAASM-1227/feat/runtime_lifecycle branch May 21, 2026 05:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant