---
title: prefactor_core.managers package
editUrl: true
head: []
template: doc
sidebar:
  hidden: false
  attrs: {}
pagefind: true
draft: false
---

# prefactor_core.managers package

Manager exports for prefactor-core.

### *class* prefactor_core.managers.AgentInstanceHandle(instance_id: str, client: [PrefactorCoreClient](prefactor_core.md#prefactor_core.PrefactorCoreClient))

Bases: `object`

Handle to an agent instance with convenience methods.

This class provides a clean interface for:
- Starting and finishing the instance
- Creating spans within the instance
- Managing the instance lifecycle

### Example

async with client.create_agent_instance(…) as instance:
: await instance.start()
  <br/>
  async with instance.span(“agent:llm”) as span:
  : span.set_payload({“model”: “gpt-4”})
    # … do work …
  <br/>
  await instance.finish()

#### *async* create_span(schema_name: str, parent_span_id: str | None = None, payload: dict[str, Any] | None = None) → str

Create a span within this instance and return its ID.

The span stays open until finish_span() is called.

* **Parameters:**
  * **schema_name** – Name of the schema for this span.
  * **parent_span_id** – Optional explicit parent span ID.
  * **payload** – Optional initial payload (params/inputs) stored on creation.
* **Returns:**
  The span ID.

#### *async* finish(status: FinishStatus = 'complete') → None

Mark the instance as finished.

This queues a finish operation for the instance.

* **Parameters:**
  **status** – Terminal status for the instance — one of `"complete"`,
  `"failed"`, or `"cancelled"`. Defaults to `"complete"`.

#### *async* finish_span(span_id: str, result_payload: dict[str, Any] | None = None) → None

Finish a previously created span.

* **Parameters:**
  * **span_id** – The ID of the span to finish.
  * **result_payload** – Optional result data to store on the span.

#### *property* id *: str*

Get the instance ID.

* **Returns:**
  The unique identifier for this agent instance.

#### span(schema_name: str, parent_span_id: str | None = None, payload: dict[str, Any] | None = None)

Create a span within this instance.

This is a convenience method that delegates to the client.

* **Parameters:**
  * **schema_name** – Name of the schema for this span.
  * **parent_span_id** – Optional explicit parent span ID.
  * **payload** – Optional initial payload (params/inputs) stored on creation.
* **Yields:**
  SpanContext for the created span.

#### *async* start() → None

Mark the instance as started.

This queues a start operation for the instance.

### *class* prefactor_core.managers.AgentInstanceManager(http_client: [PrefactorHttpClient](../../http/reference/prefactor_http.md#prefactor_http.PrefactorHttpClient), enqueue: Callable[[[Operation](prefactor_core.operations.md#prefactor_core.operations.Operation)], Awaitable[None]])

Bases: `object`

Manages agent instance lifecycle operations.

This class provides a high-level interface for agent instance operations.
Registration is done synchronously to get the API-generated ID, while
start/finish operations are queued for async processing.

### Example

manager = AgentInstanceManager(http_client, enqueue_func)

# Register a new instance (synchronous - returns API-generated ID)
instance_id = await manager.register(

> agent_id=”my-agent”,
> agent_version={“name”: “1.0.0”},
> agent_schema_version={“version”: “1.0.0”}

)

# Start the instance (queued)
await manager.start(instance_id)

# Finish the instance (queued)
await manager.finish(instance_id)

#### *async* finish(instance_id: str, status: FinishStatus = 'complete') → None

Mark an instance as finished.

Queues a finish operation for the instance.

* **Parameters:**
  * **instance_id** – The ID of the instance to finish.
  * **status** – Terminal status for the instance. Defaults to `"complete"`.

#### *async* finish_with_idempotency_key(instance_id: str, idempotency_key: str, status: FinishStatus = 'complete') → None

Queue a finish operation using a stable idempotency key.

#### *async* register(agent_id: str, agent_version: dict[str, Any], agent_schema_version: dict[str, Any], instance_id: str | None = None) → str

Register a new agent instance.

Makes a synchronous API call to register the instance and returns
the API-generated ID.

* **Parameters:**
  * **agent_id** – ID of the agent to create an instance for.
  * **agent_version** – Version information (name, external_identifier, etc.).
  * **agent_schema_version** – Schema version information.
  * **instance_id** – Optional ID to forward to the API as `id`.  When
    provided, the API uses it as the instance ID; when omitted,
    the API generates one.
* **Returns:**
  The instance ID (API-generated).

#### *async* start(instance_id: str) → None

Mark an instance as started.

Queues a start operation for the instance.

* **Parameters:**
  **instance_id** – The ID of the instance to start.

#### *async* start_with_idempotency_key(instance_id: str, idempotency_key: str) → None

Queue a start operation using a stable idempotency key.

### *class* prefactor_core.managers.SpanManager(http_client: [PrefactorHttpClient](../../http/reference/prefactor_http.md#prefactor_http.PrefactorHttpClient), enqueue: Callable[[[Operation](prefactor_core.operations.md#prefactor_core.operations.Operation)], Awaitable[None]])

Bases: `object`

Manages span lifecycle operations.

Spans follow a three-phase lifecycle that maps to the API’s state machine:

1. `prepare()`  — synchronous; allocates a local temp ID and pushes it
   onto the SpanContextStack so nested spans can auto-detect their parent.
   No HTTP call is made.
2. `start()`    — async; POSTs the span to the API with status
   `"active"` and the params payload, then re-keys local state under
   the API-generated ID. The span is now running.
3. `finish()`   — async; queues a `FINISH_SPAN` operation that calls
   `POST /agent_spans/{id}/finish` with the desired terminal status
   (`complete`, `failed`, or `cancelled`).

API state machine:
: pending  → cancelled            (cancel_unstarted: POST pending, finish cancelled)
  active   → complete / failed / cancelled  (start then finish)

`cancel_unstarted()` handles the case where the span is cancelled
before `start()` is ever called — it POSTs the span as `pending`
then immediately cancels it, which is the only valid pre-active
cancellation path the API supports.

### Example

manager = SpanManager(http_client, enqueue_func)

temp_id = manager.prepare(instance_id=”inst-123”, schema_name=”agent:llm”)
api_id  = await manager.start(temp_id, payload={“model”: “gpt-4”})
await manager.finish(api_id, status=”complete”, result_payload={…})

#### *async* cancel_unstarted(temp_id: str) → None

Cancel a span that was never started.

When `cancel()` is called before `start()`, the span has not yet
been posted to the API. The API state machine only allows
`pending → cancelled`, so this method creates the span as
`pending` then immediately cancels it via the finish endpoint.

* **Parameters:**
  **temp_id** – The temporary ID returned by `prepare()`.
* **Raises:**
  **KeyError** – If temp_id is not a known pending span.

#### *async* create(instance_id: str, schema_name: str, parent_span_id: str | None = None, payload: dict[str, Any] | None = None, span_id: str | None = None) → str

Create a span in one step (prepare + start).

Convenience method that combines `prepare()` and `start()` for
callers that don’t need the two-phase lifecycle.

* **Parameters:**
  * **instance_id** – ID of the agent instance this span belongs to.
  * **schema_name** – Name of the schema for this span.
  * **parent_span_id** – Optional parent span ID (auto-detected if None).
  * **payload** – Optional initial payload data.
  * **span_id** – Ignored (API generates IDs).
* **Returns:**
  The API-generated span ID.

#### *async* finish(span_id: str, result_payload: dict[str, Any] | None = None, status: FinishStatus = 'complete', idempotency_key: str | None = None) → None

Mark a span as finished.

Queues a finish operation and removes the span from the stack.

* **Parameters:**
  * **span_id** – The ID of the span to finish.
  * **result_payload** – Optional result data to store on the span.
  * **status** – Terminal status — `"complete"`, `"failed"`, or
    `"cancelled"` (default: `"complete"`). The span must be
    `active` for this to succeed; use `cancel_unstarted()`
    to cancel a span that was never started.
  * **idempotency_key** – Optional key to make repeated finish requests
    duplicate-safe. When omitted, a new key is generated.
* **Raises:**
  **KeyError** – If the span ID is not known.

#### get_span(span_id: str) → [Span](prefactor_core.models.md#prefactor_core.models.Span) | None

Get a span by ID.

* **Parameters:**
  **span_id** – The span ID to look up.
* **Returns:**
  The span if known, None otherwise.

#### prepare(instance_id: str, schema_name: str, parent_span_id: str | None = None) → str

Reserve a local span slot and push it onto the context stack.

Allocates a temporary local ID and pushes it onto the
SpanContextStack so that nested `prepare()` calls can auto-detect
their parent. The actual HTTP POST is deferred to `start()`.

* **Parameters:**
  * **instance_id** – ID of the agent instance this span belongs to.
  * **schema_name** – Name of the schema for this span.
  * **parent_span_id** – Optional parent span ID (auto-detected from
    stack if None).
* **Returns:**
  A temporary span ID (replaced by the API-generated ID in
  `start()`).

#### *async* start(temp_id: str, payload: dict[str, Any] | None = None) → str

Post the span to the API as `active` and return the API-generated ID.

POSTs the span with `status="active"`, which allows it to be
finished via the finish endpoint with any terminal status
(`complete`, `failed`, or `cancelled`). Replaces the temporary
local ID with the API-generated ID in local state and on the context
stack.

* **Parameters:**
  * **temp_id** – The temporary ID returned by `prepare()`.
  * **payload** – Optional params/inputs to send with the span.
* **Returns:**
  The API-generated span ID.
* **Raises:**
  **KeyError** – If temp_id is not a known pending span.

## Submodules

* [prefactor_core.managers.agent_instance module](prefactor_core.managers.agent_instance.md)
  * [`AgentInstanceHandle`](prefactor_core.managers.agent_instance.md#prefactor_core.managers.agent_instance.AgentInstanceHandle)
    * [`AgentInstanceHandle.create_span()`](prefactor_core.managers.agent_instance.md#prefactor_core.managers.agent_instance.AgentInstanceHandle.create_span)
    * [`AgentInstanceHandle.finish()`](prefactor_core.managers.agent_instance.md#prefactor_core.managers.agent_instance.AgentInstanceHandle.finish)
    * [`AgentInstanceHandle.finish_span()`](prefactor_core.managers.agent_instance.md#prefactor_core.managers.agent_instance.AgentInstanceHandle.finish_span)
    * [`AgentInstanceHandle.id`](prefactor_core.managers.agent_instance.md#prefactor_core.managers.agent_instance.AgentInstanceHandle.id)
    * [`AgentInstanceHandle.span()`](prefactor_core.managers.agent_instance.md#prefactor_core.managers.agent_instance.AgentInstanceHandle.span)
    * [`AgentInstanceHandle.start()`](prefactor_core.managers.agent_instance.md#prefactor_core.managers.agent_instance.AgentInstanceHandle.start)
  * [`AgentInstanceManager`](prefactor_core.managers.agent_instance.md#prefactor_core.managers.agent_instance.AgentInstanceManager)
    * [`AgentInstanceManager.finish()`](prefactor_core.managers.agent_instance.md#prefactor_core.managers.agent_instance.AgentInstanceManager.finish)
    * [`AgentInstanceManager.finish_with_idempotency_key()`](prefactor_core.managers.agent_instance.md#prefactor_core.managers.agent_instance.AgentInstanceManager.finish_with_idempotency_key)
    * [`AgentInstanceManager.register()`](prefactor_core.managers.agent_instance.md#prefactor_core.managers.agent_instance.AgentInstanceManager.register)
    * [`AgentInstanceManager.start()`](prefactor_core.managers.agent_instance.md#prefactor_core.managers.agent_instance.AgentInstanceManager.start)
    * [`AgentInstanceManager.start_with_idempotency_key()`](prefactor_core.managers.agent_instance.md#prefactor_core.managers.agent_instance.AgentInstanceManager.start_with_idempotency_key)
* [prefactor_core.managers.span module](prefactor_core.managers.span.md)
  * [`SpanManager`](prefactor_core.managers.span.md#prefactor_core.managers.span.SpanManager)
    * [`SpanManager.cancel_unstarted()`](prefactor_core.managers.span.md#prefactor_core.managers.span.SpanManager.cancel_unstarted)
    * [`SpanManager.create()`](prefactor_core.managers.span.md#prefactor_core.managers.span.SpanManager.create)
    * [`SpanManager.finish()`](prefactor_core.managers.span.md#prefactor_core.managers.span.SpanManager.finish)
    * [`SpanManager.get_span()`](prefactor_core.managers.span.md#prefactor_core.managers.span.SpanManager.get_span)
    * [`SpanManager.prepare()`](prefactor_core.managers.span.md#prefactor_core.managers.span.SpanManager.prepare)
    * [`SpanManager.start()`](prefactor_core.managers.span.md#prefactor_core.managers.span.SpanManager.start)