orchestrata_ultimate.agents.runtime
Reference › orchestrata_ultimate › agents › runtime
runtime is the instance lifecycle manager of the Multi-Agent Runtime (specification 005, user stories US-001 and US-004). VolkRuntime is an IComponent that spawns, tracks and terminates volk instances. It is built from a VolkRegistry (volk_registry), a MultiagentPrologBridge (prolog_bridge) and an optional RedisStateManager. pool, lifecycle and the task_executor depend on it. AgentRuntime is an alias subclass.
spawn runs the registration governance check (_check_registration_governance, which raises VolkSpawnError on denial), asserts the Prolog facts for the new volk (_assert_spawn_facts, _assert_running_facts), records a VolkInstance locally (_register_instance) and persists it to Redis when a state manager is present (_persist_instance). terminate checks governance, drains the instance (_drain_gracefully) and then cleans up the facts and local tracking (_finalize_termination); force_terminate takes an emergency reason. mark_busy, mark_ready and mark_failed change instance state for the executor. Query methods are get_instance, list_instances and get_instance_health, and instance_count and active_count are properties. As an IComponent it exposes initialize, start, stop, get_health and get_metadata.
At a glance
| Source | src/orchestrata_ultimate/agents/runtime.py |
| Lines of code | 444 |
| Classes | 2 |
| Functions | 1 |
| Imports (internal) | orchestrata_ultimate.agents.constants, orchestrata_ultimate.agents.exceptions, orchestrata_ultimate.agents.prolog_bridge, orchestrata_ultimate.agents.types, orchestrata_ultimate.agents.volk_registry, orchestrata_ultimate.core.base.traces, orchestrata_ultimate.core.protocols, orchestrata_ultimate.infra.redis_state |
| Imported by | orchestrata_ultimate.agents.lifecycle, orchestrata_ultimate.agents.pool, orchestrata_ultimate.agents.task_executor |
| Tests that import it | tests/agents/test_lifecycle.py, tests/agents/test_pool.py, tests/agents/test_pool_real.py, tests/agents/test_runtime.py, tests/agents/test_runtime_real.py, tests/agents/test_task_executor.py, tests/agents/test_task_executor_coverage.py, tests/agents/test_task_executor_real.py, tests/factories/real.py, tests/generated_agents/test_coordinator_generated.py, tests/generated_agents/test_intent_adapter_generated.py, tests/generated_agents/test_pool_generated.py, tests/generated_agents/test_postman_adapter_generated.py, tests/generated_agents/test_runtime_generated.py, tests/generated_agents/test_task_executor_generated.py, tests/generated_recovery/test_agents_intent_adapter.py |
Class diagram
Dependency diagram
API
Classes
VolkRuntime
Bases: IComponent · Decorators: traces(spec='005', story='US-001', reqs=['REQ-005-US-001-001', 'REQ-005-FR3-001', 'REQ-005-US-004-001']) · Line 54
Manages Volk instance lifecycle.
| Method | Signature | Summary |
|---|---|---|
__init__ |
__init__(registry: VolkRegistry, prolog: MultiagentPrologBridge, redis_state: RedisStateManager | None = None) -> None |
|
initialize |
async initialize(config: dict[str, Any]) -> None |
|
start |
async start() -> None |
|
stop |
async stop() -> None |
|
get_health |
async get_health() -> HealthStatus |
|
get_metadata |
get_metadata() -> ComponentMetadata |
|
_check_registration_governance |
_check_registration_governance(instance_id: str, alias: str, definition: Any) -> None |
Run Prolog registration check; raise VolkSpawnError on denial. |
_assert_spawn_facts |
_assert_spawn_facts(instance_id: str, definition: Any) -> None |
Assert Prolog facts for a newly registered Volk. |
_assert_running_facts |
_assert_running_facts(instance_id: str, alias: str) -> None |
Assert Prolog running/available facts; raise VolkSpawnError if denied. |
_register_instance |
_register_instance(instance_id: str, alias: str, metadata: dict) -> VolkInstance |
Create and register the VolkInstance in local tracking. |
spawn |
async spawn(alias: str, ****kwargs: Any) -> VolkInstance |
Spawn a new Volk instance. |
_drain_gracefully |
async _drain_gracefully(instance_id: str, instance: VolkInstance) -> None |
Check governance, then drain the instance before termination. |
_finalize_termination |
_finalize_termination(instance_id: str, instance: VolkInstance) -> None |
Clean up Prolog facts, update state, and remove from alias tracking. |
terminate |
async terminate(instance_id: str, force: bool = False) -> bool |
Terminate a Volk instance. |
force_terminate |
async force_terminate(instance_id: str, reason: str) -> bool |
Force-terminate with an emergency reason. |
get_instance |
async get_instance(instance_id: str) -> VolkInstance | None |
|
list_instances |
async list_instances(alias: str | None = None, status: InstanceStatus | None = None) -> list[VolkInstance] |
|
get_instance_health |
async get_instance_health(instance_id: str) -> HealthStatus |
|
mark_busy |
mark_busy(instance_id: str, task_id: str) -> None |
Mark an instance as busy with a task. |
mark_ready |
mark_ready(instance_id: str) -> None |
Mark an instance as ready (task completed). |
mark_failed |
mark_failed(instance_id: str) -> None |
Mark an instance as failed. |
_persist_instance |
_persist_instance(instance: VolkInstance) -> None |
Persist instance state to Redis if available. |
instance_count property |
instance_count() -> int |
Total number of tracked instances (all statuses). |
active_count property |
active_count() -> int |
Number of active instances (READY or BUSY). |
AgentRuntime
Bases: VolkRuntime · Line 441
Runtime alias for VolkRuntime.
Functions
| Function | Signature | Summary |
|---|---|---|
_utc_now traces |
_utc_now() -> datetime |
Source
"""Volk Runtime — instance lifecycle management.
Implements IComponent with ComponentType.VOLK_RUNTIME. Manages spawning,
terminating, and tracking Volk instances with Prolog governance checks
and Redis state persistence.
Author: Mohamed
Spec: 005-multi-agent (amended)
"""
from __future__ import annotations
import asyncio
import json
import logging
import time
import uuid
from datetime import UTC, datetime
from typing import TYPE_CHECKING, Any
if TYPE_CHECKING:
from orchestrata_ultimate.agents.volk_registry import VolkRegistry
from orchestrata_ultimate.infra.redis_state import RedisStateManager
from orchestrata_ultimate.agents.constants import REDIS_VOLK_INSTANCE_PREFIX
from orchestrata_ultimate.agents.exceptions import VolkSpawnError, VolkTerminateError
from orchestrata_ultimate.agents.prolog_bridge import MultiagentPrologBridge
from orchestrata_ultimate.agents.types import InstanceStatus, VolkInstance
from orchestrata_ultimate.core.base.traces import traces
from orchestrata_ultimate.core.protocols import (
ComponentMetadata,
ComponentType,
HealthStatus,
IComponent,
)
_logger = logging.getLogger(__name__)
@traces(spec="005", story="US-003", reqs=["REQ-005-FR3-001"])
def _utc_now() -> datetime:
return datetime.now(UTC)
@traces(
spec="005",
story="US-001",
reqs=[
"REQ-005-US-001-001",
"REQ-005-FR3-001",
"REQ-005-US-004-001",
],
)
class VolkRuntime(IComponent):
"""Manages Volk instance lifecycle.
Coordinates with VolkRegistry for agent definitions, Prolog governance
for permission checks, and Redis for state persistence.
Parameters
----------
registry : VolkRegistry
Registry for looking up Volk definitions.
prolog : MultiagentPrologBridge
Bridge to multiagent.pl governance rules.
redis_state : RedisStateManager, optional
Redis state manager for persistence.
"""
def __init__(
self,
registry: VolkRegistry,
prolog: MultiagentPrologBridge,
redis_state: RedisStateManager | None = None,
) -> None:
self._registry = registry
self._prolog = prolog
self._redis = redis_state
self._instances: dict[str, VolkInstance] = {}
self._alias_instances: dict[str, list[str]] = {} # alias -> [instance_ids]
self._initialized = False
self._running = False
# ================================================================
# IComponent Implementation
# ================================================================
async def initialize(self, config: dict[str, Any]) -> None:
self._initialized = True
async def start(self) -> None:
self._running = True
@traces(spec="005", story="US-003", reqs=["REQ-005-NFR5-001"])
async def stop(self) -> None:
# Terminate all running instances
for iid in list(self._instances.keys()):
instance = self._instances[iid]
if instance.is_active:
try:
await self.terminate(iid)
except Exception as exc:
_logger.warning(
"Failed to terminate instance '%s' during stop; forcing TERMINATED: %s",
iid,
exc,
exc_info=True,
)
instance.status = InstanceStatus.TERMINATED
self._running = False
@traces(
spec="005",
story="US-004",
reqs=["REQ-005-US-004-001"],
)
async def get_health(self) -> HealthStatus:
if not self._initialized:
return HealthStatus.UNKNOWN
if not self._running:
return HealthStatus.STOPPED
active = [i for i in self._instances.values() if i.is_active]
failed = [
i for i in self._instances.values() if i.status == InstanceStatus.FAILED
]
if failed and not active:
return HealthStatus.UNHEALTHY
if failed:
return HealthStatus.DEGRADED
return HealthStatus.HEALTHY
def get_metadata(self) -> ComponentMetadata:
return ComponentMetadata(
id="volk-runtime",
name="VolkRuntime",
version="1.0.0",
component_type=ComponentType.VOLK_RUNTIME,
description="Volk instance lifecycle management",
)
# ================================================================
# Spawn
# ================================================================
@traces(
spec="005",
story="US-001",
reqs=["REQ-005-FR4-001"],
)
def _check_registration_governance(
self, instance_id: str, alias: str, definition: Any
) -> None:
"""Run Prolog registration check; raise VolkSpawnError on denial."""
volk_type = definition.role or "worker"
cpu = int(definition.resource_requirements.cpu_cores)
memory = definition.resource_requirements.memory_mb
if not self._prolog.can_register_volk(instance_id, volk_type, cpu, memory):
raise VolkSpawnError(
f"Prolog governance denied registration for '{alias}' "
f"(type={volk_type}, cpu={cpu}, memory={memory})",
alias=alias,
)
@traces(spec="005", story="US-001", reqs=["REQ-005-US-001-001"])
def _assert_spawn_facts(self, instance_id: str, definition: Any) -> None:
"""Assert Prolog facts for a newly registered Volk."""
self._prolog.assert_volk_registered(instance_id)
self._prolog.assert_volk_resources_allocated(instance_id)
for cap in definition.capabilities:
self._prolog.assert_volk_capable(instance_id, cap.name)
@traces(spec="005", story="US-001", reqs=["REQ-005-FR4-001"])
def _assert_running_facts(self, instance_id: str, alias: str) -> None:
"""Assert Prolog running/available facts; raise VolkSpawnError if denied."""
if not self._prolog.can_start_volk(instance_id):
raise VolkSpawnError(
f"Prolog governance denied start for '{alias}'",
alias=alias,
)
self._prolog.assert_volk_running(instance_id)
self._prolog.assert_volk_available(instance_id)
self._prolog.assert_volk_no_pending_tasks(instance_id)
@traces(spec="005", story="US-001", reqs=["REQ-005-US-001-001"])
def _register_instance(
self, instance_id: str, alias: str, metadata: dict
) -> VolkInstance:
"""Create and register the VolkInstance in local tracking."""
instance = VolkInstance(
instance_id=instance_id,
alias=alias,
status=InstanceStatus.READY,
metadata=metadata,
)
self._instances[instance_id] = instance
if alias not in self._alias_instances:
self._alias_instances[alias] = []
self._alias_instances[alias].append(instance_id)
self._persist_instance(instance)
return instance
@traces(spec="005", story="US-001", reqs=["REQ-005-US-001-001", "REQ-005-FR1-001"])
async def spawn(self, alias: str, **kwargs: Any) -> VolkInstance:
"""Spawn a new Volk instance.
Flow:
1. VolkRegistry.get_volk(alias) -- get registration
2. prolog.can_register_volk() -- governance check
3. Assert Prolog facts: registered, resources_allocated, capabilities
4. prolog.can_start_volk() -- lifecycle check
5. Assert volk_running
6. Create VolkInstance, persist to Redis
7. Return VolkInstance
Raises
------
VolkSpawnError
If the alias is not registered, governance denies spawn,
or any step in the spawn flow fails.
"""
start_time = time.monotonic()
registration = self._registry.get_volk(alias)
if registration is None:
raise VolkSpawnError(
f"Alias '{alias}' not found in VolkRegistry", alias=alias
)
definition = registration.definition
instance_id = kwargs.get("instance_id", str(uuid.uuid4()))
self._check_registration_governance(instance_id, alias, definition)
self._assert_spawn_facts(instance_id, definition)
self._assert_running_facts(instance_id, alias)
instance = self._register_instance(
instance_id, alias, kwargs.get("metadata", {})
)
elapsed_ms = (time.monotonic() - start_time) * 1000
_logger.info(
f"Spawned instance {instance_id} for '{alias}' in {elapsed_ms:.1f}ms"
)
return instance
# ================================================================
# Terminate
# ================================================================
@traces(
spec="005",
story="US-003",
reqs=["REQ-005-FR3-001", "REQ-005-NFR5-001"],
)
async def _drain_gracefully(self, instance_id: str, instance: VolkInstance) -> None:
"""Check governance, then drain the instance before termination."""
self._prolog.assert_volk_no_pending_tasks(instance_id)
if not self._prolog.can_stop_volk(instance_id):
raise VolkTerminateError(
f"Prolog governance denied stop for instance '{instance_id}'",
instance_id=instance_id,
)
instance.status = InstanceStatus.DRAINING
if instance.current_task:
await asyncio.sleep(0.01)
@traces(spec="005", story="US-003", reqs=["REQ-005-FR3-001"])
def _finalize_termination(self, instance_id: str, instance: VolkInstance) -> None:
"""Clean up Prolog facts, update state, and remove from alias tracking."""
self._prolog.retract_volk_running(instance_id)
self._prolog.retract_volk_available(instance_id)
instance.status = InstanceStatus.TERMINATED
instance.current_task = None
alias_list = self._alias_instances.get(instance.alias, [])
if instance_id in alias_list:
alias_list.remove(instance_id)
self._persist_instance(instance)
@traces(
spec="005",
story="US-003",
reqs=["REQ-005-AC5-001", "REQ-005-FR3-001"],
)
async def terminate(self, instance_id: str, force: bool = False) -> bool:
"""Terminate a Volk instance.
Graceful: checks governance, drains tasks, then terminates.
Force: bypasses task drain.
"""
instance = self._instances.get(instance_id)
if instance is None:
raise VolkTerminateError(
f"Instance '{instance_id}' not found",
instance_id=instance_id,
)
if instance.status == InstanceStatus.TERMINATED:
return True
if not force:
await self._drain_gracefully(instance_id, instance)
self._finalize_termination(instance_id, instance)
_logger.info(
f"Terminated instance {instance_id} "
f"(force={force}, tasks_completed={instance.tasks_completed})"
)
return True
@traces(spec="005", story="US-003", reqs=["REQ-005-NFR5-001"])
async def force_terminate(self, instance_id: str, reason: str) -> bool:
"""Force-terminate with an emergency reason."""
instance = self._instances.get(instance_id)
if instance is None:
raise VolkTerminateError(
f"Instance '{instance_id}' not found",
instance_id=instance_id,
)
if not self._prolog.can_force_stop_volk(instance_id, reason):
raise VolkTerminateError(
f"Prolog governance denied force stop for '{instance_id}' "
f"(reason={reason})",
instance_id=instance_id,
)
return await self.terminate(instance_id, force=True)
# ================================================================
# Query
# ================================================================
async def get_instance(self, instance_id: str) -> VolkInstance | None:
return self._instances.get(instance_id)
async def list_instances(
self,
alias: str | None = None,
status: InstanceStatus | None = None,
) -> list[VolkInstance]:
instances = list(self._instances.values())
if alias is not None:
instances = [i for i in instances if i.alias == alias]
if status is not None:
instances = [i for i in instances if i.status == status]
return instances
@traces(spec="001", story="US-001", reqs=["REQ-001-018"])
async def get_instance_health(self, instance_id: str) -> HealthStatus:
instance = self._instances.get(instance_id)
if instance is None:
return HealthStatus.UNKNOWN
if instance.status == InstanceStatus.TERMINATED:
return HealthStatus.STOPPED
if instance.status == InstanceStatus.FAILED:
return HealthStatus.UNHEALTHY
if instance.status == InstanceStatus.DRAINING:
return HealthStatus.DEGRADED
# Check Prolog health
if self._prolog.volk_healthy(instance_id):
return HealthStatus.HEALTHY
return HealthStatus.DEGRADED
# ================================================================
# Instance State Management
# ================================================================
@traces(spec="005", story="US-003", reqs=["REQ-005-FR3-001"])
def mark_busy(self, instance_id: str, task_id: str) -> None:
"""Mark an instance as busy with a task."""
instance = self._instances.get(instance_id)
if instance is None:
return
instance.status = InstanceStatus.BUSY
instance.current_task = task_id
instance.last_activity = _utc_now()
self._prolog.retract_volk_available(instance_id)
self._prolog.assert_volk_busy(instance_id)
self._prolog.retract_volk_no_pending_tasks(instance_id)
@traces(spec="005", story="US-003", reqs=["REQ-005-FR3-001"])
def mark_ready(self, instance_id: str) -> None:
"""Mark an instance as ready (task completed)."""
instance = self._instances.get(instance_id)
if instance is None:
return
instance.status = InstanceStatus.READY
instance.current_task = None
instance.last_activity = _utc_now()
self._prolog.retract_volk_busy(instance_id)
self._prolog.assert_volk_available(instance_id)
self._prolog.assert_volk_no_pending_tasks(instance_id)
@traces(spec="005", story="US-003", reqs=["REQ-005-FR3-001"])
def mark_failed(self, instance_id: str) -> None:
"""Mark an instance as failed."""
instance = self._instances.get(instance_id)
if instance is None:
return
instance.status = InstanceStatus.FAILED
instance.current_task = None
self._prolog.retract_volk_running(instance_id)
self._prolog.retract_volk_available(instance_id)
self._prolog.assert_volk_failed(instance_id)
# ================================================================
# Persistence
# ================================================================
@traces(spec="005", story="US-003", reqs=["REQ-005-FR3-001"])
def _persist_instance(self, instance: VolkInstance) -> None:
"""Persist instance state to Redis if available."""
if self._redis is None:
return
key = f"{REDIS_VOLK_INSTANCE_PREFIX}:{instance.instance_id}"
try:
self._redis.client.set(key, json.dumps(instance.to_dict()), ex=3600)
except Exception as e:
_logger.warning(f"Failed to persist instance {instance.instance_id}: {e}")
@property
@traces(spec="005", story="US-004", reqs=["REQ-005-AC6-001"])
def instance_count(self) -> int:
"""Total number of tracked instances (all statuses)."""
return len(self._instances)
@property
@traces(spec="005", story="US-004", reqs=["REQ-005-AC6-001"])
def active_count(self) -> int:
"""Number of active instances (READY or BUSY)."""
return sum(1 for i in self._instances.values() if i.is_active)
# Class alias for orchestrata-ultimate naming
class AgentRuntime(VolkRuntime):
"""Runtime alias for VolkRuntime."""
pass