angee.agents.backends
Inference backend protocol and the bundled built-in backend.
An inference provider row selects one backend via backend_class. Vendor backend addons (openai, anthropic, …) wrap official SDK clients and list models live; the built-in manual backend has no client and leaves the catalogue hand-curated.
ChatAPI
class ChatAPI(StrEnum)The chat protocol an inference backend speaks to its vendor.
A vendor-neutral fact each backend declares, so a consumer that must pick a protocol adapter reads the declaration instead of switching on vendor identity. That is what lets an OpenAI-compatible backend (Ollama, a local router, a hosted gateway) inherit the right adapter from its base class without the consumer growing a branch per vendor.
It is deliberately coarser than a vendor: many vendors speak OPENAI_CHAT. A new protocol adds a member here and one builder in the consuming runtime; a new vendor on an existing protocol adds neither.
InferenceModelSpec
@dataclass(frozen=True, slots=True)
class InferenceModelSpec()One model a backend advertises, in the shape InferenceModel rows carry.
Empty/zero optional fields let the upsert preserve richer hand-entered or seeded metadata instead of overwriting it on a live refresh.
upsert_defaults
def upsert_defaults() -> dict[str, Any]Return the InferenceModel upsert defaults this spec contributes.
Empty/zero optional fields are omitted so a live refresh preserves richer hand-entered or seeded metadata instead of overwriting it.
InferenceRequest
@dataclass(frozen=True, slots=True)
class InferenceRequest()Provider-neutral request for one non-streaming chat completion.
InferenceResponse
@dataclass(frozen=True, slots=True)
class InferenceResponse()Provider-neutral response returned by a backend chat call.
InferenceBackend
class InferenceBackend(ImplBase)The strategy one inference provider resolves to.
Subclasses read the API credential, endpoint, and config directly from the provider row that selected them.
__init__
def __init__(provider: Any) -> NoneBind this backend to its provider row.
connect_oauth_client
def connect_oauth_client(owner_label: str) -> AnyReturn the enabled OAuth client this backend connects its provider through.
The backend's oauth_client hint is the only source; an empty hint is not connectable. The bound provider's vendor slug feeds the {vendor} template.
system_preamble
def system_preamble(credential: Any | None = None) -> strReturn the vendor-required system-prompt opening for credential.
Most (vendor × credential-kind) pairs need none. Anthropic's OAuth (Personal Plans) edge refuses requests whose system prompt does not open with the Claude Code identity line; that backend overrides this. Callers prepend a non-empty preamble ahead of their own instructions. credential defaults to the bound provider's.
list_models
def list_models() -> Sequence[InferenceModelSpec]Return the provider's advertised models for catalogue upsert.
chat
def chat(request: InferenceRequest) -> InferenceResponseSend one non-streaming chat request through this provider.
ManualInferenceBackend
class ManualInferenceBackend(InferenceBackend)Built-in backend with no client — its catalogue is curated by hand.
The default registry entry: a provider on this backend lists no models to sync, so its :class:InferenceModel rows are entered through the console. A vendor backend addon supplies the live-listing alternative.
list_models
def list_models() -> Sequence[InferenceModelSpec]Return no models; the catalogue is maintained by hand on this backend.