/\ ATFGraph /docs
README Downloads
Python SDK / ATFGraph
Framework reference

This article is retained from the existing framework docs. Self-hosting commands and server-admin access differ from the managed CLI workflow. Start with Get started for the installed product.

Python API reference

Use these tables to find SDK classes and methods by task. They summarize common public interfaces; the numbered chapters explain how to use them. They are not an exhaustive generated inventory, so consult your installed package's signature for newer options. async marks coroutine methods, and / joins retained aliases. Names normally come from atfgraph; rows name a submodule when needed.

Authoring

NamePurpose
Agent(node_id, *, graph_server=None, version="0.1.0", api_key=None, description="", capacity=8, max_waiting=None, model=None, client=None, poll_interval=0.1, tags=None, sync_emitters=True, harness_provider=None, harness_cwd=None, media=None, http_pool=None, record_usage_events=True, report_usage=True)One label + version worth of capabilities, plus the client and worker that serve them
AgentRouter(prefix="", tags=None)A group of handlers an Agent includes; decorated functions stay callable
CapabilityEntryThe registered handler record returned by Agent.add / Agent.entry
traversal(name=None, *, agent=None, **options), skill(...)Module-level decorators on the current agent (Agent.set_current)
traverse(target, *args, **kwargs)Module-level nested call using the current execution context's agent
capability_to_tool_schema(target, capability)OpenAI-format function tool for one label.capability

Choose an Agent method according to the work you need to do:

ThemeMethods
Registrationtraversal(name=None, **options), skill(name=None, **options), add(kind, func, name=None, **options), include_router(router), capabilities(), definition(), entry(capability), target(capability), label, set_current(), async register()
Servingrun(*, capacity=None, once=False, register=True), async serve(*, stop=None, capacity=None, register=True, once=False, sync_emitters=None, startup_timeout=30.0), attach_worker(worker), worker, bind_client(client), use_transport(transport), client
Callingasync traverse(target, *args, timeout=None, **kwargs) / call, traverse_sync(...), async submit(target, input=None, *, session_id=None, operation_key=None, idempotency_key=None, version=None), async call_local(capability, *args, **kwargs)
Contextctx, cancel_requested(), async progress(data), async note(message, tags=None), async bind_session(session_id), async request_approval(prompt, *, operation_key, checkpoint=None) / pause, async save_checkpoint(name, value, *, expected_revision=None), async load_checkpoint(name, default=None)
Facadesmemory, knowledge, emitters, discovery, identities, credentials, observability, media, model, http_pool
Model and mediaasync ai(...), ai_with_vision, ai_with_audio, ai_with_multimodal, ai_generate_image, ai_generate_audio, ai_generate_music, ai_generate_video, ai_transcribe_audio, async realtime_session(*, model=None, provider="openai", transport="websocket", **options)
Harnessasync harness(prompt, *, provider=None, schema=None, cwd=None, **options), harness_doctor(providers=None)
Emittersemitter_bindings(), has_emitter_bindings(), async sync_emitters(), synced_emitters, webhook_urls(), on_change(patterns, **options)
Discoveryasync discover(**filters)
Usage and logscost_tracker(), execution_cost(), async record_usage(entry), usage_reporting(), enable_node_logs(logger=None, *, level=20, max_pending=1000, batch_size=100, flush_interval=1.0, exclude=()), async disable_node_logs(), node_logs

AgentRouter groups handlers before an Agent includes them. It provides traversal(...), skill(...), add(kind, func, name=None, *, max_attempts=1, timeout_seconds=300, description=None, input_schema=None, output_schema=None, tags=None, triggers=None, accepts_manual_emitters=True), async ai(...), async traverse(...), async submit(...), and memory.

The client and server facades below use HTTP. Local helpers such as trackers, rate limiters and caches keep state in the worker process unless their documentation explicitly describes server storage.

Client

NamePurpose and methods
Client(server=None, *, api_key=None, bearer_token=None, edge_auth=None, timeout=30.0, poll_interval=0.2, max_poll_interval=2.0, transport=None, headers=None, limits=None, stream_limits=None, http2=False, max_in_flight=100, max_pending=1000)Async client; one per event loop, use async with. Traversers: async submit(target, input=None, *, version=None, session_id=None, idempotency_key=None, parent_step_id=None, operation_key=None, parent_lease_token=None), traverse(target, input=None, *, timeout=None, **submit_kwargs), wait(traverser_id, *, timeout=None, poll_interval=None), get, cancel, path, event_log(traverser_id, after=0), events(traverser_id, *, last_event_id=None, reconnect=True, max_reconnects=20), list_traversers. Registry: register_agent(label, version, capabilities), capabilities(label, version=None), list_agents. Sessions: create_session. Memory: memory_read, memory_write, memory_delete. Approvals and checkpoints: request_approval(*, operation_key, prompt, checkpoint=None, pause=True), get_approval, list_approvals, decide_approval(approval_id, decision, response=None), put_checkpoint, get_checkpoint. Artifacts: put_artifact, get_artifact, read_artifact, list_artifacts, delete_artifact. Server: health, server_info. Worker protocol: worker_enroll, worker_claim, worker_renew, worker_progress, worker_suspend, worker_resume, worker_complete, worker_drain. Also server, transport, async aclose
HandleA submitted traverser (id, step_id, status, target): async result(timeout=None), wait(timeout=None, *, poll_interval=None), refresh, cancel, path, event_log(after=0), events(last_event_id=None), last
ATFGraphClientCompatibility adapter: execute returns {"result": ..., "status": ...}; execute_async, wait_for_execution_result, poll_execution_status, cancel_async_execution, create_session, aclose
Submission, TraverserResult, Path, PathStep, Event, AgentDefinition, Capability, ServerInfo, ClaimedTask, MemoryValueWire models. TraverserResult has status, output, error, is_terminal, ok; Path.items holds PathSteps with step_id, traverser_id, target, status, parent_step_id, attempts, raw; Event has sequence, type, data
TERMINAL_STATESfrozenset({"succeeded", "failed", "cancelled", "timed_out"})
UsageEventA usage entry recorded as a progress event; UsageEvent.from_event(event) returns None for other events

Execution context

NamePurpose and methods
ExecutionContextThe leased task: fields traverser_id, step_id, root_id, target, version, lease_token, attempt, session_id, worker_id, trigger, input, parent_id; properties label, capability, traversal_name, agent_node_id, is_root, execution_id, parent_execution_id, run_id, workflow_id, effective_session_id, emitter, via_emitter, cancel_requested, child_waits, permit_released; operation_key(target, payload), child(**overrides)
current_context(), require_context()The current context, or None / NoExecutionContext
use_context(ctx)Context manager binding an explicit context (tests, scripts)
session_scope(session_id)Within a handler, direct default memory and child submissions at session_id

Memory and knowledge

NamePurpose and methods
Memoryapp.memory: scope factories session(session_id=None), actor(actor_id=None), workflow(root_id=None), global_() / global_scope(), default(); direct operations with scope=: async get, read, set, update, delete, exists, keys, list_keys, set_vector, get_vector, delete_vector, similarity_search, search, changes; watch(patterns=None, *, scope=None), on_change(patterns, *, scope=None, after=0, interval=0.25), async run_subscriptions(stop)
MemoryScopeOne bound scope with the same operations: read, get, exists, set, delete, update, keys, list_keys, set_vector, get_vector, delete_vector, similarity_search, search, changes, watch, subscription
MemoryChangeEvent, ChangePage, KeyPage, VectorValue, VectorMatch, SearchResultChange-feed entries (action is set or delete), key pages and vector results
Knowledge(client_provider, scope="global", *, session_id=None, actor_id=None, root_id=None, normalize=True)Scope-bound document knowledge (BM25): async put(doc_id, text=None, *, title=None, chunks=None, metadata=None, chunk_size=None, chunk_overlap=None, expected_revision=None), put_many(documents), get(doc_id, *, include_chunks=True), list(*, prefix=None, cursor=None, limit=None), documents(...), delete(doc_id, *, expected_revision=None), search(query, *, top_k=10, offset=0, filters=None, doc_id=None, min_score=None), search_all(...), static search_across(scopes, query, ...), stats(); scope(scope, ...), semantic(embedding, *, index="knowledge", filter_keys=None), label
KnowledgeHit, KnowledgeSearchResult, KnowledgeDocument, KnowledgeChunk, KnowledgeDocumentSummary, KnowledgeListing, KnowledgeWriteResult, KnowledgeBatchResult, KnowledgeStatsResults. KnowledgeSearchResult.citations() and context(max_chars=...); KnowledgeHit.citation is doc_id#ordinal
chunk_text(...)Preview of the server's chunker (same algorithm)
SemanticKnowledgeSemantic and hybrid retrieval over one scope: async put, put_many, delete, search, stats, embed_query, reindex, reindex_all; scope, config, dimension
EmbeddingConfig(provider, model, dimension=..., batch_size=..., concurrency=..., max_attempts=..., retry_delay=...), EmbeddingProvider, Embedder, http_embedding_provider(url, model, api_key=None)How chunks and queries are embedded; EmbeddingProvider is the callable type Sequence[str] -> Sequence[Sequence[float]]
SemanticHit, SemanticSearchResult, SemanticWriteResult, SemanticBatchResult, SemanticStats, IndexResult, IndexFailureSemantic results and indexing outcomes

Model and media

NamePurpose and methods
ModelProviderBase: async complete(...), stream(...); provider_name, capabilities
HTTPChatModel, AnthropicMessagesModelOpenAI-compatible /chat/completions and Anthropic Messages providers; from_env(), complete, stream
ModelResponsetext, parsed, model, usage, tool_calls, finish_reason, provider, audio, images; wants_tools, cost_usd, assistant_message()
ModelStream, StreamEventAsync iterator from ai(stream=True): text(), collect(), response(), aclose()
ToolCall, ToolCallResponse, ToolCallRecord, ToolCallTraceResult of app.ai(tools=...): final text or parsed output plus the full trace
HTTPPoolOne bounded httpx.AsyncClient shared by every provider: client(), request, stream, aclose
Image, Audio, Video, File, TextInput parts; Image.from_url/from_file/from_bytes, Audio.from_url/from_file/from_bytes, to_part(). Helpers image_from_url, image_from_file, audio_from_url, audio_from_file, video_from_url, video_from_file, file_from_url, file_from_path, text
MultimodalResponsetext, audio, images, videos, files, model, provider, usage, cost_usd, cost_source; has_audio, has_images, is_multimodal, save_all(directory, prefix=...)
ImageOutput, AudioOutput, VideoOutput, FileOutputProduced media (url, is_inline, save(path))
MediaRouter, MediaProvider, OpenAIMediaProvider, OpenRouterMediaProvider, FalMediaProvider, MiniMaxMediaProvider, default_media_router()Longest-prefix routing of (model, modality) to a provider: register, set_default, default_model, resolve, describe, providers
MediaFetcherExplicit downloads for http(s) media URLs: fetch, download
CostEntry(model, provider=None, source="llm", operation="chat", input_tokens=0, output_tokens=0, total_tokens=0, cache_read_tokens=0, cache_creation_tokens=0, cost_usd=None, cost_source=None, capability=None, extra={}), CostTracker, execution_cost(ctx=None), use_tracker(tracker=None)Per-execution accounting; totals(), entries, and total_cost_usd (sum of known prices, None when none are known). Check has_unknown_costs or calls_without_price for incomplete totals

Harness

NamePurpose
HarnessResult(text, provider="atf-harness", session_id=None, model=None, usage={}, returncode=0, parsed=None, duration_ms=0, turns=0, cost_usd=None, events=[], remote=None)One harness run; result, is_error, input_tokens, output_tokens, total_tokens
atfgraph.harness: RemoteHarness(base_url, profile, edge_auth=None, app_token_env=None, model=None, thinking=None, timeout=30.0, poll_interval=2.0, metadata={}), ExistingWorkspace(cwd), RemoteHarnessMetadata, RemoteHarnessClient, RemoteHarnessError, HarnessResetRequired, remote_harness_doctor(transport)Remote transport for Agent.harness(..., transport=, workspace=): typed HTTP/SSE client, credential-free configuration (edge provider + named token variable), the metadata a remote run attaches as HarnessResult.remote, and the doctor that checks reachability/readiness/profile without a turn. See 07-harness.md.
HarnessFailureA failed or interrupted harness invocation, never a fabricated answer
harness_doctor(providers=None, *, binaries=None), ProviderHealthWhich provider CLIs are installed; looks up executables only, never runs them

Emitters

NamePurpose and methods
ScheduleTrigger(cron=None, timezone="UTC", every_seconds=None, input={}, code_origin=None) / ScheduleEmitterBind a capability to a schedule; to_binding(capability, *, version=None), matches, source
EventTrigger(source, types=[], secret_env=None, config={}, code_origin=None, transform=None) / EventEmitterBind a capability to an authenticated webhook source; matches(source, event_type), to_binding
TriggerUnion[EventTrigger, ScheduleTrigger]
on_schedule(cron=None, *, timezone="UTC", every_seconds=None, input=None), on_event(source, *, types=None, secret_env=None, config=None, transform=None)Decorators staging a trigger on the next registration
TriggerContext / EmitterContextctx.trigger for an emitter delivery: trigger_id, source, event_type, event_id, idempotency_key, received_at, managed_by, vc_id; emitter_id, code_managed, to_dict()
async simulate_trigger(entry_or_func, *, source, body=None, event_type="", event_id=None, idempotency_key=None, trigger_id=None, received_at=None, managed_by="code")Run a handler in-process as if an emitter delivery of source had fired
TransformErrorThe registered transform rejected or could not process a delivery
Emitters(client)Server-side emitter administration: async create(name, target, *, kind=None, source=None, input=None, version=None, interval_seconds=None, cron_expression=None, timezone=None, event_types=None, secret_env=None, source_config=None), list, get, update(emitter_id, *, expected_revision, enabled=None, managed_by=None), delete, events(emitter_id), fire(emitter_id, delivery_key, *, input=None), replay(emitter_id, event_id), sync(label, bindings), metrics; webhook_url(emitter)
Emitter, InboundEventEmitter definition and one received delivery

Discovery and multi-node

NamePurpose and methods
Discover(client)Namespace-scoped registry: async agents(), capabilities(*, label=None, version=None, name=None, kind=None, query="", limit=None, offset=0), resolve(target, *, version=None), invoke(target, input=None, *, version=None, timeout=None, **options), publications(*, query=None), publish(label, *, version=None, protocol="http", published=False, display_name=None, description=None), remove_publication(publication_id), settings()
AgentMesh(client, labels)The same view restricted to selected labels; callable as mesh(**filters)
DiscoveredCapabilitylabel, version, capability, target; async submit, invoke pinned to that version
PublicationA managed descriptor returned by publish
OfflineMesh(agents, *, title=..., worker_id="offline-mesh", actor_id="offline", propagate_usage=True)Several nodes in one process behind one ASGI app with an offline graph: async open, aclose, invoke, submit, serve_async; serve, client(), discovery, app, health(), usage(root_id), resolve(node_id), node_ids, is_open, bound_port(). Importable from atfgraph.offline; not in atfgraph.__all__

Identity and credentials

NamePurpose and methods
Identity(client)Server-held Ed25519 node keys and signed paths: async create(label), list(*, label=None), rotate(key_id), revoke(key_id), sign(traverser_id, key_id), proofs(traverser_id), verify(proof)
NodeIdentity, PathProof, VerificationKey record (id, label, algorithm, public_key, state), signed snapshot (to_dict()), verdict (valid, trusted, key_state, algorithm)
Credentials(client_provider)DIDs and W3C credentials: for_client(client); async enroll(label), dids(), did(label, *, web_base_url=None), resolve(did), issue(issuer_label, *, kind=None, traverser_id=None, subject=None, type=None, expires_in_seconds=None, parent_id=None, ctx=None), issue_execution(traverser_id=None, *, issuer_label=None, expires_in_seconds=None, parent_id=None, ctx=None), get(credential_id, *, ctx=None), list(*, issuer_label=None, node_label=None, traverser_id=None, root_id=None, subject_id=None, kind=None, parent_id=None, revoked=None, limit=None), verify(credential, *, at=None, resolve_remote=False, ctx=None), revoke(credential_id, reason=None), tags(*, label=None, state=None), propose_tags(label, tags), decide_tags(label, decision, *, tags=None, reason=None), tag_policy(), set_tag_policy(*, default_mode=None, rules=None, issuer_label=None)
DidEnrolment, DidResolution, Credential, CredentialPage, CredentialVerificationResults; Credential.subject, Credential.revoked; CredentialVerification.valid, trusted, reason, failed_checks
TagLedger, TagEntry, TagPolicy, TagProposalResult, TagDecisionResultTag ledger types; TagPolicy.mode_for(tag), TagLedger.approved, TagProposalResult.pending. TagRule is in atfgraph.credentials

Observability

NamePurpose and methods
Observability(client_provider)for_client(client); async record_usage(entries, *, ctx=None, traverser_id=None), usage(*, traverser_id=None, root_id=None, limit=100, cursor=None, ctx=None), usage_totals(*, since=None, until=None, group_by="run", root_id=None, principal=None, all_principals=False), log(message, level="info", *, stream="app", source="sdk", **fields), append_logs(entries, *, ctx=None, traverser_id=None), query_logs(*, traverser_id=None, root_id=None, levels=None, stream=None, since=None, until=None, after=0, limit=100, contains=None, ctx=None), tail_logs(...), run_metadata(root_id=None, *, ctx=None), set_run_metadata(root_id=None, *, set=None, unset=None, ctx=None), settings(), set_settings(*, node_logs_enabled=None, node_logs_max_message_bytes=None), webhook(), set_webhook(url, *, secret_env=None, headers=None, event_types=None, enabled=True), delete_webhook(), webhook_status(), test_webhook(message=...), redrive_webhook(limit=100)
UsageReceipt, UsageRecord, UsagePage, UsageReport, UsageTotalsDurable usage results; UsageReport.by_key, UsageTotals.cost_complete, UsageRecord.cost_known
LogReceipt, LogRecord, LogPageNode-log results; LogPage.next_cursor
RunMetadataroot_id, metadata, entries, updated_at; mlflow_trace_id, mlflow_experiment_url
WebhookConfig, WebhookStatusWebhook configuration (secret_present, never the secret) and delivery counters
UsageShipper, NodeLogHandler, UsageReportingThe pieces Agent uses: stable call_ids per attempt; a logging.Handler with pending(), flush_async(), dropped, shipped, failed, last_error; the counters behind Agent.usage_reporting()
atfgraph.mlflowOptional module (enable, enable_from_env, disable, trace, span, settings, stats, flush, current_trace_id, trace_headers, join_trace); not part of atfgraph.__all__

Controls

NamePurpose and methods
RateLimitPolicy(rate=None, per=1.0, burst=None, concurrency=None, max_pending=100)rate admissions per per seconds (token bucket of burst tokens) plus a concurrency cap and a bounded waiting queue
RateLimiter(default=None, *, policies=None, clock=None)Per-key admission for one event loop: async acquire(key, *, timeout=None), release(key), limit(key, *, timeout=None), async run(key, func, *args, timeout=None, **kwargs), set_policy, policy_for, stats(key), in_flight, pending
RateLimitExceeded, RateLimitStatsRefusal (queue full or deadline passed) and counters
ResultCache(*, ttl=300.0, max_size=1024, sweep_interval=30.0, clock=None)Expiring, size-bounded, single-flight cache: get, set, delete, clear, keys, expires_in, async get_or_compute(key, factory, *, ttl=None), start, async stop(*, clear=False), sweep, in_flight, sweeping
CacheStatsCache counters
ModelRouter(*, limiter=None, admission_timeout=None)A ModelProvider dispatching to registered providers only: register(name, provider, *, models=(), prefixes=(), default=False, default_model=None, limit_key=None), unregister, resolve(model=None, *, needs=None), async complete, stream, routes, default_route, capabilities
ProviderRouteOne registered route (name, provider, models, prefixes, default_model, limit_key; matches)
async retry_rate_limited(func, *, max_attempts=3, base_delay=0.2, max_delay=5.0, deadline=None, sleep=asyncio.sleep, clock=None)Retry func() on HTTP 429 with capped exponential backoff, honouring retry_after

Hosting

NamePurpose and methods
Worker, WorkerStatsThe outbound worker behind Agent.serve: async enroll, run(stop), drain(timeout=...), abandon_running; stats claimed, succeeded, failed, cancelled, paused, lease_lost, stale_completions, max_concurrent
ServerlessHost(agent, *, client=None, capacity=None, max_duration=30.0, register=True, sync_emitters=False, claim_interval=0.01, max_idle_interval=0.1, min_heartbeat=0.2, shutdown_grace=1.0), serverless_host(spec_or_agent, **options)One bounded invocation per event: async handle(event), handle_sync(event), entrypoint(*, safety_margin=1.0), async aclose(*, drain=False), client
Invocation, ServerlessEventError, ServerlessLoadErrorParsed event (action, capability, input, session_id, idempotency_key, timeout, include_path) and its failures
RealtimeSession, RealtimeEvent, SessionTurn, SessionDefinition, build_session_definition(...), validate_session_transport(...), RealtimeError, SessionTransportErrorLive OpenAI Realtime session: async connect, send_text, append_audio, commit_audio, create_response, cancel_response, send_function_result, events(), turn(), close. validate_session_transport accepts only the transports that work

Testing

NamePurpose
atfgraph.testing.FakeGraphServer(*, lease_seconds=30.0, api_keys=None, product="ATFGraph vNext", version="0.0.0-fake")In-memory contract double over httpx.MockTransport for fast SDK unit tests: transport(), client(**kwargs), advance(seconds), fail_next(path_suffix, *, status=500, times=1, method=None), records(*, target=None, root_id=None), count(target). It is not the graph server; see ./15-testing.md for the real-daemon fixture
atfgraph.testing.serve_agent(agent, server, *, capacity=None)Async context manager running an agent's worker against the fake
atfgraph.testing.FakeError, atfgraph.testing.IdentityThe fake's error and its token identity (namespace, principal, roles)
atfgraph.testing.emitter_fixture_sources(), load_emitter_fixture(source)Packaged emitter delivery fixtures

Errors

NameRaised when
ATFGraphErrorBase class for every SDK error
APIErrorThe graph server answered with an error envelope (status, code, message)
AuthError401 or 403
NotFoundError404
ConflictError409: immutable definition changed, stale lease, revision mismatch
ValidationError400 or 422
TransportErrorThe HTTP request never produced a response
TraversalErrorA traverser reached a terminal state other than succeeded; subclasses TraversalFailed, TraversalCancelled, TraversalTimedOut
WaitTimeoutThe client-side wait deadline passed before a terminal state
HandlerError(message, *, code="handler_error", retryable=False), RetryableError(message, *, code="retryable")Raised from a handler to control the error envelope (to_envelope()); RetryableError is the retryable shorthand
LeaseLostThe worker no longer holds the lease for a task
NoExecutionContextA context-bound operation was used outside a worker task
ModelNotConfiguredapp.ai was called without a configured model provider
ModelError, MediaError, MediaCapabilityError, MediaProviderNotConfiguredProvider answered badly; media payload unusable; provider cannot do what was asked (no request sent); missing media API key
EmbeddingError, SemanticIndexErrorEmbedding provider failed; lexical write succeeded but vector indexing did not finish
RateLimitExceeded, TransformError, RealtimeError, SessionTransportError, ServerlessEventError, ServerlessLoadError, HarnessFailureListed with their groups above

Next

ATFGraph documentationHosted workflow · Framework reference