Core Prefactor SDK with async queue-based operations
Project description
Prefactor Core
High-level Prefactor SDK with async queue-based processing.
Features
- Queue-Based Processing: Operations are queued and processed asynchronously by a worker pool
- Non-Blocking API: Agent execution is never blocked by observability calls
- Automatic Parent Detection: Nested spans automatically detect their parent from the context stack
- Schema Registry: Compose and register span schemas before instance creation
- Configurable Workers: Tune concurrency and retry behavior for the background queue
Installation
pip install prefactor-core
Quick Start
import asyncio
from prefactor_core import PrefactorCoreClient, PrefactorCoreConfig, SchemaRegistry
from prefactor_http import HttpClientConfig
registry = SchemaRegistry()
registry.register_type(
name="agent:llm",
params_schema={
"type": "object",
"properties": {
"model": {"type": "string"},
"prompt": {"type": "string"},
},
"required": ["model", "prompt"],
},
result_schema={
"type": "object",
"properties": {"response": {"type": "string"}},
},
title="LLM Call",
description="A call to a language model",
template="{{model}}: {{prompt}} → {{response}}",
)
async def main():
config = PrefactorCoreConfig(
http_config=HttpClientConfig(
api_url="https://api.prefactor.ai",
api_token="your-token",
),
schema_registry=registry,
)
async with PrefactorCoreClient(config) as client:
instance = await client.create_agent_instance(
agent_id="my-agent",
agent_version={"name": "My Agent", "external_identifier": "v1.0.0"},
)
await instance.start()
async with instance.span("agent:llm") as span:
await span.start({"model": "gpt-4", "prompt": "Hello"})
result = await call_llm()
await span.complete({"response": result})
await instance.finish()
asyncio.run(main())
API Reference
PrefactorCoreClient
The main entry point. Use as an async context manager or call initialize() / close() manually.
client = PrefactorCoreClient(config)
await client.initialize()
# ... use client ...
await client.close()
create_agent_instance
handle = await client.create_agent_instance(
agent_id="my-agent",
agent_version={"name": "My Agent", "external_identifier": "v1.0.0"},
agent_schema_version=None, # Optional: auto-generated if schema_registry is configured
external_schema_version_id=None, # Optional: reference an existing schema version
) -> AgentInstanceHandle
span (context manager)
async with client.span(
instance_id="instance_123",
schema_name="agent:llm",
parent_span_id=None, # Optional: auto-detected from context stack if omitted
payload=None, # Optional: used as params if span.start() is never called explicitly
) as span:
await span.start({"model": "gpt-4", "prompt": "Hello"})
result = await call_llm()
await span.complete({"response": result})
AgentInstanceHandle
Returned by create_agent_instance. Manages the lifecycle of a single agent instance.
handle.id # -> str
await handle.start()
await handle.finish()
async with handle.span("agent:llm") as span:
...
SpanContext
The object yielded by span context managers. Spans follow a three-phase lifecycle:
- Enter context — span is prepared locally, no HTTP call yet.
await span.start(payload)— POSTs the span to the API asactivewith the given params payload.await span.complete(result)/span.fail(result)/span.cancel()— finishes the span with a terminal status.
If start() or a finish method is not called explicitly, the context manager handles them automatically on exit.
span.id # -> str (API-generated after start())
await span.start(payload: dict) # POST span as active with params payload
await span.complete(result: dict) # finish with status "complete"
await span.fail(result: dict) # finish with status "failed"
await span.cancel() # finish with status "cancelled"
span.set_result(data: dict) # accumulate result data for auto-finish
await span.finish() # finish with current status (default: "complete")
Status note: cancel() can be called before or after start(). If called before start(), the span is posted as pending and immediately cancelled — the only valid pre-active cancellation path the API supports.
Full lifecycle example
async with instance.span("agent:llm") as span:
await span.start({"model": "gpt-4", "prompt": "Hello"})
try:
result = await call_llm()
await span.complete({"response": result})
except Exception as exc:
await span.fail({"error": str(exc)})
# Cancel before starting (e.g. a conditional step that is skipped):
async with instance.span("agent:retrieval") as span:
if not needed:
await span.cancel()
else:
await span.start({"query": "..."})
docs = await retrieve()
await span.complete({"documents": docs, "count": len(docs)})
Configuration
from prefactor_core import PrefactorCoreConfig, QueueConfig
from prefactor_http import HttpClientConfig
config = PrefactorCoreConfig(
http_config=HttpClientConfig(
api_url="https://api.prefactor.ai",
api_token="your-token",
),
queue_config=QueueConfig(
num_workers=3, # Number of background workers
max_retries=3, # Retries per operation
retry_delay_base=1.0, # Base delay (seconds) for exponential backoff
),
schema_registry=None, # Optional: SchemaRegistry instance
)
Schema Registry
Use SchemaRegistry to compose span schemas from multiple sources and auto-generate the agent_schema_version passed to create_agent_instance.
from prefactor_core import SchemaRegistry
registry = SchemaRegistry()
registry.register_type(
name="agent:llm",
params_schema={
"type": "object",
"properties": {
"model": {"type": "string"},
"prompt": {"type": "string"},
},
"required": ["model", "prompt"],
},
result_schema={
"type": "object",
"properties": {"response": {"type": "string"}},
},
title="LLM Call",
description="A call to a language model",
template="{{model}}: {{prompt}} → {{response}}",
)
registry.register_type(
name="agent:tool",
params_schema={"type": "object", "properties": {...}},
result_schema={"type": "object", "properties": {...}},
title="Tool Call",
)
config = PrefactorCoreConfig(
http_config=...,
schema_registry=registry,
)
async with PrefactorCoreClient(config) as client:
# agent_schema_version is generated automatically from the registry
instance = await client.create_agent_instance(
agent_id="my-agent",
agent_version={"name": "My Agent", "external_identifier": "v1.0.0"},
)
Error Handling
from prefactor_core import (
PrefactorCoreError,
ClientNotInitializedError,
ClientAlreadyInitializedError,
OperationError,
InstanceNotFoundError,
SpanNotFoundError,
)
Architecture
The client uses a three-layer design:
- Queue infrastructure:
InMemoryQueue+TaskExecutorworker pool process operations in the background - Managers:
AgentInstanceManagerandSpanManagertranslate high-level calls intoOperationobjects and route them to the HTTP client - Client API:
PrefactorCoreClientexposes the user-facing interface and wires the layers together
All observability operations are enqueued and executed asynchronously — the calling code is never blocked waiting for API responses.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file prefactor_core-0.1.1.tar.gz.
File metadata
- Download URL: prefactor_core-0.1.1.tar.gz
- Upload date:
- Size: 24.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.28 {"installer":{"name":"uv","version":"0.9.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"25.10","id":"questing","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
52bd8aaf991526bbc8883b18bbc07523c431eaff7ca9f8976592b47bda2a93bf
|
|
| MD5 |
34a8e12579c0d103c7859863c41d9db6
|
|
| BLAKE2b-256 |
cff71660f4d9ae04ca5e3432662b2905cae562a291d7efca4f36a908057e0e65
|
File details
Details for the file prefactor_core-0.1.1-py3-none-any.whl.
File metadata
- Download URL: prefactor_core-0.1.1-py3-none-any.whl
- Upload date:
- Size: 27.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.28 {"installer":{"name":"uv","version":"0.9.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"25.10","id":"questing","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
976d61433dde9bc851d857dc5842335109afb2b9d02d4ea259db5e940e2c4b4f
|
|
| MD5 |
f631c2f62ba3323923b91acc34ada4f4
|
|
| BLAKE2b-256 |
d52772c281e86702a3c252d1288530748bff831f0db7f432a6a17843da9fa457
|