API reference¶
Generated from the apogee-ai-workflow source with mkdocstrings. Every symbol below is exported from apogee_ai_workflow, so it is part of the supported public surface.
Application · DTOs¶
CancelRunDTO
¶
GateDecisionDTO
¶
Bases: BaseModel
ResumeRunDTO
¶
StartRunDTO
¶
Application · Use cases¶
ApproveGateUseCase
¶
ApproveGateUseCase(gates: IHumanGateGateway)
Source code in apogee_ai_workflow/application/use_cases/approve_gate_use_case.py
execute
async
¶
execute(dto: GateDecisionDTO) -> HumanGate
CancelRunUseCase
¶
CancelRunUseCase(runs: IRunRepository, engine: IWorkflowEngine)
Source code in apogee_ai_workflow/application/use_cases/cancel_run_use_case.py
execute
async
¶
Source code in apogee_ai_workflow/application/use_cases/cancel_run_use_case.py
async def execute(self, run_id: str) -> bool:
run = await self._runs.find(run_id)
if run is None:
raise RunNotFoundException(run_id)
ack = await self._engine.cancel(run_id)
if run.is_terminal:
return ack
run.status = RunStatus.CANCELLED
run.finished_at = datetime.now(timezone.utc)
await self._runs.save(run)
return ack
GetRunUseCase
¶
GetRunUseCase(runs: IRunRepository)
Source code in apogee_ai_workflow/application/use_cases/get_run_use_case.py
execute
async
¶
execute(run_id: str) -> WorkflowRun
ListGatesUseCase
¶
ListGatesUseCase(gates: IHumanGateGateway)
ListRunsUseCase
¶
ListRunsUseCase(runs: IRunRepository)
Source code in apogee_ai_workflow/application/use_cases/list_runs_use_case.py
execute
async
¶
execute(*, workflow_name: str | None = None, limit: int | None = None) -> list[WorkflowRun]
RegisterWorkflowUseCase
¶
RegisterWorkflowUseCase(repository: IWorkflowRepository)
Source code in apogee_ai_workflow/application/use_cases/register_workflow_use_case.py
execute
async
¶
execute(definition: WorkflowDefinition, *, version: int = 1, replace: bool = False) -> Workflow
Source code in apogee_ai_workflow/application/use_cases/register_workflow_use_case.py
async def execute(
self,
definition: WorkflowDefinition,
*,
version: int = 1,
replace: bool = False,
) -> Workflow:
if not replace and await self._repository.exists(definition.name):
raise WorkflowAlreadyRegistered(definition.name)
workflow = Workflow(definition=definition, version=version)
return await self._repository.save(workflow)
RejectGateUseCase
¶
RejectGateUseCase(gates: IHumanGateGateway)
Source code in apogee_ai_workflow/application/use_cases/approve_gate_use_case.py
execute
async
¶
execute(dto: GateDecisionDTO) -> HumanGate
ResumeRunUseCase
¶
ResumeRunUseCase(workflows: IWorkflowRepository, runs: IRunRepository, engine: IWorkflowEngine)
Source code in apogee_ai_workflow/application/use_cases/resume_run_use_case.py
execute
async
¶
execute(run_id: str) -> WorkflowRun
Source code in apogee_ai_workflow/application/use_cases/resume_run_use_case.py
async def execute(self, run_id: str) -> WorkflowRun:
run = await self._runs.find(run_id)
if run is None:
raise RunNotFoundException(run_id)
workflow = await self._workflows.find(run.workflow_name)
if workflow is None:
raise WorkflowNotFoundException(run.workflow_name)
run = await self._engine.resume(workflow.definition, run)
return await self._runs.save(run)
StartRunUseCase
¶
StartRunUseCase(workflows: IWorkflowRepository, runs: IRunRepository, engine: IWorkflowEngine)
Source code in apogee_ai_workflow/application/use_cases/start_run_use_case.py
execute
async
¶
execute(dto: StartRunDTO) -> WorkflowRun
Source code in apogee_ai_workflow/application/use_cases/start_run_use_case.py
async def execute(self, dto: StartRunDTO) -> WorkflowRun:
workflow = await self._workflows.find(dto.workflow_name)
if workflow is None:
raise WorkflowNotFoundException(dto.workflow_name)
run = WorkflowRun(
workflow_name=workflow.name,
workflow_version=workflow.version,
input=dict(dto.input),
tenant_id=dto.tenant_id,
user_id=dto.user_id,
metadata=dict(dto.metadata),
)
await self._runs.save(run)
run = await self._engine.execute(workflow.definition, run)
return await self._runs.save(run)
Domain¶
Checkpoint
dataclass
¶
Checkpoint(run_id: str, step_name: str, sequence: int, state: dict[str, Any], output: dict[str, Any] = dict(), created_at: datetime = (lambda: now(utc))())
CompensationFailed
¶
EngineConfig
dataclass
¶
EngineConfig(max_concurrency: int = 8, default_step_timeout_seconds: float = 300.0, checkpoint_after_each_step: bool = True, persist_step_outputs: bool = True)
EngineUnavailable
¶
GateDecision
¶
Bases: str, Enum
GateNotFound
¶
GateRejected
¶
Bases: WorkflowError
Source code in apogee_ai_workflow/domain/exceptions/workflow_exceptions.py
HumanGate
dataclass
¶
HumanGate(id: str = (lambda: token_hex(8))(), run_id: str = '', step_name: str = '', label: str = '', decision: GateDecision = PENDING, reason: str | None = None, decided_at: datetime | None = None, decided_by: str | None = None, created_at: datetime = (lambda: now(utc))(), expires_at: datetime | None = None, metadata: dict[str, str] = dict())
RetryPolicy
dataclass
¶
RetryPolicy(kind: RetryPolicyKind = NONE, max_attempts: int = 1, backoff_seconds: float = 1.0, max_backoff_seconds: float = 60.0, jitter: float = 0.1)
delay_for
¶
Source code in apogee_ai_workflow/domain/value_objects/retry_policy.py
def delay_for(self, attempt: int) -> float:
if self.kind == RetryPolicyKind.NONE or attempt <= 0:
return 0.0
if self.kind == RetryPolicyKind.FIXED:
return min(self.backoff_seconds, self.max_backoff_seconds)
# EXPONENTIAL: backoff * 2^(attempt-1)
delay = self.backoff_seconds * (2 ** (attempt - 1))
return min(delay, self.max_backoff_seconds)
RunContext
dataclass
¶
RunContext(run_id: str, workflow_name: str, tenant_id: str | None = None, user_id: str | None = None, correlation_id: str | None = None, metadata: dict[str, str] = dict())
Per-run identity + immutable metadata threaded through every step.
metadata
class-attribute
instance-attribute
¶
RunStatus
¶
Bases: str, Enum
SagaCompensation
dataclass
¶
SagaCompensation(step_name: str, succeeded: bool, error: str | None = None, started_at: datetime = (lambda: now(utc))(), finished_at: datetime | None = None)
Record of a compensating action invoked during rollback.
started_at
class-attribute
instance-attribute
¶
Step
dataclass
¶
Step(name: str, handler: StepHandler | None = None, kind: StepKind = TASK, depends_on: tuple[str, ...] = tuple(), retry: RetryPolicy = RetryPolicy(), timeout_seconds: float | None = None, compensation: StepHandler | None = None, gate_label: str | None = None, description: str | None = None, metadata: dict[str, str] = dict())
Static definition of a single step within a Workflow.
depends_on
class-attribute
instance-attribute
¶
retry
class-attribute
instance-attribute
¶
retry: RetryPolicy = field(default_factory=RetryPolicy)
compensation
class-attribute
instance-attribute
¶
compensation: StepHandler | None = None
Optional compensating action invoked when the run is rolled back.
gate_label
class-attribute
instance-attribute
¶
Human-readable label shown to approvers when kind == HUMAN_GATE.
metadata
class-attribute
instance-attribute
¶
StepHandler
module-attribute
¶
Signature: async def handler(io: StepIO) -> dict | Any.
StepIO
dataclass
¶
StepIO(step_name: str, input: dict[str, Any], state: dict[str, Any], context: RunContext, attempt: int = 1)
Inputs + accumulated outputs visible to a single step handler.
input is the merge of upstream step outputs (by name) plus the
initial run input. state is the read-write store the engine
persists across checkpoints (handlers may add keys to it).
StepRun
dataclass
¶
StepRun(step_name: str, status: StepStatus = PENDING, attempt: int = 0, started_at: datetime | None = None, finished_at: datetime | None = None, output: dict[str, Any] = dict(), error: str | None = None, gate_id: str | None = None, metadata: dict[str, str] = dict())
StepStatus
¶
Bases: str, Enum
Workflow
dataclass
¶
Workflow(definition: WorkflowDefinition, version: int = 1, registered_at: datetime = (lambda: now(utc))(), metadata: dict[str, str] = dict())
WorkflowAlreadyRegistered
¶
WorkflowDefinition
dataclass
¶
WorkflowDefinition(name: str, steps: tuple[Step, ...] = tuple(), description: str | None = None, tags: tuple[str, ...] = tuple())
Logical workflow shape: name + steps DAG.
Validates non-cyclic dependencies at construction time.
steps
class-attribute
instance-attribute
¶
steps: tuple[Step, ...] = field(default_factory=tuple)
tags
class-attribute
instance-attribute
¶
topological_order
¶
topological_order() -> list[Step]
Return steps in a valid execution order (deps before dependents).
Source code in apogee_ai_workflow/domain/entities/workflow_definition.py
def topological_order(self) -> list[Step]:
"""Return steps in a valid execution order (deps before dependents)."""
order: list[Step] = []
visited: set[str] = set()
adjacency = {s.name: s for s in self.steps}
def visit(name: str) -> None:
if name in visited:
return
visited.add(name)
step = adjacency[name]
for dep in step.depends_on:
visit(dep)
order.append(step)
for s in self.steps:
visit(s.name)
return order
WorkflowRun
dataclass
¶
WorkflowRun(id: str = (lambda: token_hex(8))(), workflow_name: str = '', workflow_version: int = 1, status: RunStatus = PENDING, input: dict[str, Any] = dict(), state: dict[str, Any] = dict(), started_at: datetime = (lambda: now(utc))(), finished_at: datetime | None = None, steps: dict[str, StepRun] = dict(), error: str | None = None, pending_gate_id: str | None = None, tenant_id: str | None = None, user_id: str | None = None, metadata: dict[str, str] = dict())
Mutable record of a single workflow execution.
Domain · Enums¶
RetryPolicyKind
¶
StepKind
¶
Bases: str, Enum
Domain · Exceptions¶
RunNotFoundException
¶
StepFailedException
¶
Bases: WorkflowError
Source code in apogee_ai_workflow/domain/exceptions/workflow_exceptions.py
WorkflowError
¶
Bases: Exception
Base for apogee-ai-workflow errors.
WorkflowNotFoundException
¶
Domain · Protocols (ports)¶
ICheckpointer
¶
Bases: Protocol
save
async
¶
save(checkpoint: Checkpoint) -> None
list
async
¶
list(run_id: str) -> list[Checkpoint]
latest
async
¶
latest(run_id: str) -> Checkpoint | None
clear
async
¶
IHumanGateGateway
¶
IRunRepository
¶
Bases: Protocol
save
async
¶
save(run: WorkflowRun) -> WorkflowRun
get
async
¶
get(run_id: str) -> WorkflowRun
find
async
¶
find(run_id: str) -> WorkflowRun | None
list
async
¶
list(*, workflow_name: str | None = None, limit: int | None = None) -> list[WorkflowRun]
ISagaCompensator
¶
Bases: Protocol
compensate
async
¶
compensate(definition: WorkflowDefinition, run: WorkflowRun) -> list[SagaCompensation]
IWorkflowEngine
¶
Bases: Protocol
execute
async
¶
execute(definition: WorkflowDefinition, run: WorkflowRun) -> WorkflowRun
resume
async
¶
resume(definition: WorkflowDefinition, run: WorkflowRun) -> WorkflowRun
cancel
async
¶
shutdown
async
¶
healthcheck
async
¶
IWorkflowRepository
¶
Infrastructure¶
DBOSAdapter
¶
Adapter for dbos-inc DBOS durable runtime.
Lazy import: install via pip install 'apogee-ai-workflow[dbos]'.
Source code in apogee_ai_workflow/infrastructure/engines/dbos_adapter.py
execute
async
¶
execute(definition: WorkflowDefinition, run: WorkflowRun) -> WorkflowRun
Source code in apogee_ai_workflow/infrastructure/engines/dbos_adapter.py
resume
async
¶
resume(definition: WorkflowDefinition, run: WorkflowRun) -> WorkflowRun
cancel
async
¶
shutdown
async
¶
healthcheck
async
¶
DefaultSagaCompensator
¶
Walks succeeded steps in reverse and invokes compensation handlers.
Compensation failure does not abort the rollback — every record is captured so callers can decide what to do with the partial state.
compensate
async
¶
compensate(definition: WorkflowDefinition, run: WorkflowRun) -> list[SagaCompensation]
Source code in apogee_ai_workflow/infrastructure/saga/default_saga_compensator.py
async def compensate(
self,
definition: WorkflowDefinition,
run: WorkflowRun,
) -> list[SagaCompensation]:
order = list(definition.topological_order())
# Reverse to process most-recent successful work first
ordered_names = [step.name for step in order]
succeeded = [n for n in reversed(ordered_names) if n in run.succeeded_steps]
results: list[SagaCompensation] = []
for name in succeeded:
step = definition.step(name)
if step.compensation is None:
continue
io = StepIO(
step_name=step.name,
input=dict(run.steps[name].output),
state=run.state,
context=RunContext(
run_id=run.id,
workflow_name=run.workflow_name,
tenant_id=run.tenant_id,
user_id=run.user_id,
),
attempt=run.steps[name].attempt,
)
started = datetime.now(timezone.utc)
try:
result = step.compensation(io)
if inspect.iscoroutine(result):
await result
run.steps[name].compensate()
results.append(
SagaCompensation(
step_name=step.name,
succeeded=True,
started_at=started,
finished_at=datetime.now(timezone.utc),
)
)
except Exception as exc: # noqa: BLE001 - compensation must not abort rollback
results.append(
SagaCompensation(
step_name=step.name,
succeeded=False,
error=str(exc),
started_at=started,
finished_at=datetime.now(timezone.utc),
)
)
finally:
# Cooperative yield so other compensations can interleave
await asyncio.sleep(0)
return results
has_run_succeeded
staticmethod
¶
has_run_succeeded(run: WorkflowRun, step_name: str) -> bool
InMemoryCheckpointer
¶
Source code in apogee_ai_workflow/infrastructure/checkpoints/in_memory_checkpointer.py
save
async
¶
save(checkpoint: Checkpoint) -> None
list
async
¶
list(run_id: str) -> list[Checkpoint]
latest
async
¶
latest(run_id: str) -> Checkpoint | None
clear
async
¶
InMemoryHumanGateGateway
¶
Source code in apogee_ai_workflow/infrastructure/hil/in_memory_human_gate_gateway.py
open
async
¶
update
async
¶
list
async
¶
Source code in apogee_ai_workflow/infrastructure/hil/in_memory_human_gate_gateway.py
async def list(
self,
*,
run_id: str | None = None,
pending_only: bool = False,
) -> list[HumanGate]:
items = list(self._store.values())
if run_id is not None:
items = [g for g in items if g.run_id == run_id]
if pending_only:
items = [g for g in items if g.is_pending]
items.sort(key=lambda g: g.created_at)
return items
InMemoryRunRepository
¶
Source code in apogee_ai_workflow/infrastructure/registry/in_memory_run_repository.py
save
async
¶
save(run: WorkflowRun) -> WorkflowRun
get
async
¶
get(run_id: str) -> WorkflowRun
find
async
¶
find(run_id: str) -> WorkflowRun | None
list
async
¶
list(*, workflow_name: str | None = None, limit: int | None = None) -> list[WorkflowRun]
Source code in apogee_ai_workflow/infrastructure/registry/in_memory_run_repository.py
async def list(
self,
*,
workflow_name: str | None = None,
limit: int | None = None,
) -> list[WorkflowRun]:
items = sorted(self._store.values(), key=lambda r: r.started_at, reverse=True)
if workflow_name is not None:
items = [r for r in items if r.workflow_name == workflow_name]
if limit is not None:
items = items[:limit]
return items
InMemoryWorkflowRepository
¶
JsonCheckpointer
¶
One file per <root>/<run_id>.jsonl — append-only checkpoints.
Source code in apogee_ai_workflow/infrastructure/checkpoints/json_checkpointer.py
save
async
¶
save(checkpoint: Checkpoint) -> None
list
async
¶
list(run_id: str) -> list[Checkpoint]
latest
async
¶
latest(run_id: str) -> Checkpoint | None
clear
async
¶
JsonHumanGateGateway
¶
File-backed gateway: <root>/<gate_id>.json.
Source code in apogee_ai_workflow/infrastructure/hil/json_human_gate_gateway.py
open
async
¶
update
async
¶
list
async
¶
Source code in apogee_ai_workflow/infrastructure/hil/json_human_gate_gateway.py
async def list(
self,
*,
run_id: str | None = None,
pending_only: bool = False,
) -> list[HumanGate]:
items = await asyncio.to_thread(self._read_all)
if run_id is not None:
items = [g for g in items if g.run_id == run_id]
if pending_only:
items = [g for g in items if g.is_pending]
items.sort(key=lambda g: g.created_at)
return items
JsonRunRepository
¶
One file per <root>/<run_id>.json plus _index.json.
Source code in apogee_ai_workflow/infrastructure/registry/json_run_repository.py
save
async
¶
save(run: WorkflowRun) -> WorkflowRun
get
async
¶
get(run_id: str) -> WorkflowRun
find
async
¶
find(run_id: str) -> WorkflowRun | None
list
async
¶
list(*, workflow_name: str | None = None, limit: int | None = None) -> list[WorkflowRun]
NativeWorkflowEngine
¶
NativeWorkflowEngine(*, checkpointer: ICheckpointer | None = None, gates: IHumanGateGateway | None = None, compensator: ISagaCompensator | None = None, config: EngineConfig | None = None)
Async DAG executor with checkpointing, retries, saga, HIL.
Steps are executed respecting depends_on order; independent steps
run concurrently up to EngineConfig.max_concurrency. After every
step the engine writes a :class:Checkpoint so resumption from a
crashed worker only repeats steps that didn't finish.
HUMAN_GATE steps pause the run, persist a :class:HumanGate via the
gateway and return — the run state is WAITING_FOR_GATE until
resume() is invoked after the gateway records a decision.
Source code in apogee_ai_workflow/infrastructure/engines/native_engine.py
def __init__(
self,
*,
checkpointer: ICheckpointer | None = None,
gates: IHumanGateGateway | None = None,
compensator: ISagaCompensator | None = None,
config: EngineConfig | None = None,
) -> None:
self._checkpointer = checkpointer
self._gates = gates or InMemoryHumanGateGateway()
self._compensator = compensator or DefaultSagaCompensator()
self._config = config or EngineConfig()
self._cancelled: set[str] = set()
execute
async
¶
execute(definition: WorkflowDefinition, run: WorkflowRun) -> WorkflowRun
resume
async
¶
resume(definition: WorkflowDefinition, run: WorkflowRun) -> WorkflowRun
Source code in apogee_ai_workflow/infrastructure/engines/native_engine.py
async def resume(
self,
definition: WorkflowDefinition,
run: WorkflowRun,
) -> WorkflowRun:
if run.pending_gate_id is not None:
gate = await self._gates.find(run.pending_gate_id)
if gate is None:
raise GateRejected(run.pending_gate_id, "gate not found")
if gate.is_pending:
# Still pending — return the run unchanged so the caller
# can show ``WAITING_FOR_GATE`` to the user.
return run
if gate.decision.value == "rejected":
step_run = run.step_run(gate.step_name)
step_run.fail(f"gate rejected: {gate.reason or ''}")
run.error = f"gate rejected: {gate.reason or ''}"
run.status = RunStatus.FAILED
run.finished_at = datetime.now(timezone.utc)
run.pending_gate_id = None
return run
# Approved → mark gate step as succeeded and continue
step_run = run.step_run(gate.step_name)
step_run.succeed(output={"gate": "approved"})
run.pending_gate_id = None
return await self._drive(definition, run)
cancel
async
¶
shutdown
async
¶
healthcheck
async
¶
RestateAdapter
¶
Adapter for restate.dev durable orchestration.
Lazy import: install via pip install 'apogee-ai-workflow[restate]'.
Source code in apogee_ai_workflow/infrastructure/engines/restate_adapter.py
def __init__(self, *, ingress_url: str = "http://localhost:8080") -> None:
try:
import restate # type: ignore # noqa: F401
except ImportError as exc:
raise ImportError(
"RestateAdapter requires `restate-sdk`. "
"Install with: pip install 'apogee-ai-workflow[restate]'"
) from exc
self._ingress_url = ingress_url
execute
async
¶
execute(definition: WorkflowDefinition, run: WorkflowRun) -> WorkflowRun
Source code in apogee_ai_workflow/infrastructure/engines/restate_adapter.py
async def execute(
self,
definition: WorkflowDefinition,
run: WorkflowRun,
) -> WorkflowRun:
# Real implementation would invoke a Restate service via ingress.
# We surface a clear error so the caller knows infra is missing.
raise EngineUnavailable(
self.name,
"RestateAdapter.execute requires a deployed Restate service mapped to "
f"workflow {definition.name!r}",
)
resume
async
¶
resume(definition: WorkflowDefinition, run: WorkflowRun) -> WorkflowRun
cancel
async
¶
shutdown
async
¶
healthcheck
async
¶
SqlCheckpointer
¶
SQLAlchemy 2.x async checkpointer.
Lazy import via [sql] extra. Schema is one row per checkpoint;
composite PK = (run_id, sequence).
Source code in apogee_ai_workflow/infrastructure/checkpoints/sql_checkpointer.py
def __init__(
self,
session_factory: Any,
*,
table_name: str = "apogee_workflow_checkpoints",
) -> None:
try:
import sqlalchemy # type: ignore # noqa: F401
except ImportError as exc: # pragma: no cover
raise ImportError(
"SqlCheckpointer requires SQLAlchemy. "
"Install with: pip install 'apogee-ai-workflow[sql]'"
) from exc
self._session_factory = session_factory
self._table_name = table_name
self._table = self._build_table()
ensure_schema
async
¶
save
async
¶
save(checkpoint: Checkpoint) -> None
Source code in apogee_ai_workflow/infrastructure/checkpoints/sql_checkpointer.py
async def save(self, checkpoint: Checkpoint) -> None:
from sqlalchemy import insert
async with self._session_factory() as session:
await session.execute(
insert(self._table).values(
run_id=checkpoint.run_id,
sequence=checkpoint.sequence,
step_name=checkpoint.step_name,
state=dict(checkpoint.state),
output=dict(checkpoint.output),
created_at=checkpoint.created_at,
)
)
await session.commit()
list
async
¶
list(run_id: str) -> list[Checkpoint]
Source code in apogee_ai_workflow/infrastructure/checkpoints/sql_checkpointer.py
async def list(self, run_id: str) -> list[Checkpoint]:
from sqlalchemy import select
async with self._session_factory() as session:
stmt = (
select(self._table)
.where(self._table.c.run_id == run_id)
.order_by(self._table.c.sequence)
)
rows = (await session.execute(stmt)).all()
return [self._from_row(r._mapping) for r in rows]
latest
async
¶
latest(run_id: str) -> Checkpoint | None
Source code in apogee_ai_workflow/infrastructure/checkpoints/sql_checkpointer.py
async def latest(self, run_id: str) -> Checkpoint | None:
from sqlalchemy import desc, select
async with self._session_factory() as session:
stmt = (
select(self._table)
.where(self._table.c.run_id == run_id)
.order_by(desc(self._table.c.sequence))
.limit(1)
)
row = (await session.execute(stmt)).first()
if row is None:
return None
return self._from_row(row._mapping)
clear
async
¶
Source code in apogee_ai_workflow/infrastructure/checkpoints/sql_checkpointer.py
TemporalAdapter
¶
TemporalAdapter(*, target: str = 'localhost:7233', namespace: str = 'default', task_queue: str = 'apogee-workflow')
Adapter for Temporal.io durable workflow engine.
Lazy import: install via pip install 'apogee-ai-workflow[temporal]'.
The native Apogee step model maps onto Temporal activities; full code-gen of Temporal workflows is out of scope for this MVP. The adapter exposes the contract surface so callers can opt into Temporal when the surrounding org already runs it.
Source code in apogee_ai_workflow/infrastructure/engines/temporal_adapter.py
def __init__(
self,
*,
target: str = "localhost:7233",
namespace: str = "default",
task_queue: str = "apogee-workflow",
) -> None:
try:
import temporalio # type: ignore # noqa: F401
except ImportError as exc:
raise ImportError(
"TemporalAdapter requires `temporalio`. "
"Install with: pip install 'apogee-ai-workflow[temporal]'"
) from exc
self._target = target
self._namespace = namespace
self._task_queue = task_queue
execute
async
¶
execute(definition: WorkflowDefinition, run: WorkflowRun) -> WorkflowRun
Source code in apogee_ai_workflow/infrastructure/engines/temporal_adapter.py
async def execute(
self,
definition: WorkflowDefinition,
run: WorkflowRun,
) -> WorkflowRun:
try:
from temporalio.client import Client # type: ignore
except ImportError as exc: # pragma: no cover
raise EngineUnavailable(self.name, str(exc)) from exc
try:
client = await Client.connect(self._target, namespace=self._namespace)
await client.start_workflow(
definition.name,
args=[run.input],
id=run.id,
task_queue=self._task_queue,
)
except Exception as exc: # noqa: BLE001
raise EngineUnavailable(self.name, str(exc)) from exc
return run
resume
async
¶
resume(definition: WorkflowDefinition, run: WorkflowRun) -> WorkflowRun
cancel
async
¶
Source code in apogee_ai_workflow/infrastructure/engines/temporal_adapter.py
async def cancel(self, run_id: str) -> bool:
try:
from temporalio.client import Client # type: ignore
except ImportError:
return False
try:
client = await Client.connect(self._target, namespace=self._namespace)
handle = client.get_workflow_handle(run_id)
await handle.cancel()
return True
except Exception: # noqa: BLE001
return False
shutdown
async
¶
healthcheck
async
¶
WorkflowEngineRegistry
¶
WorkflowEngineRegistry(engines: Mapping[str, IWorkflowEngine] | None = None)
Source code in apogee_ai_workflow/infrastructure/registry/engine_registry.py
register
¶
register(engine: IWorkflowEngine) -> None
unregister
¶
get
¶
get(name: str) -> IWorkflowEngine
find
¶
find(name: str) -> IWorkflowEngine | None