API reference¶
Generated from the apogee-ai source with mkdocstrings. Every symbol below is exported from apogee_ai, so it is part of the supported public surface.
Other¶
ActionAuditPort
¶
Bases: Protocol
Records an audited action (adapter delegates to ai-audit's hash-chain).
record_tool
async
¶
record_tool(ctx: GovernanceContext, *, tool_name: str, status: str, detail: str = '') -> None
Agent
dataclass
¶
Agent(name: str = '', slug: str = '', version: str = '0.1.0', description: str = '', status: AgentStatusEnum = DRAFT, visibility: AgentVisibilityEnum = PRIVATE, owner_id: str | None = None, tags: list[str] = list(), agent_type: AgentTypeEnum = WORKER, execution_pattern: ExecutionPatternEnum = REACT, collaboration_pattern: CollaborationPatternEnum = HIERARCHICAL, engine: EngineBinding = EngineBinding(), model: ModelConfig = ModelConfig(), prompt: PromptConfig = PromptConfig(), memory: MemoryConfig = MemoryConfig(), runtime: RuntimeConfig = RuntimeConfig(), tools: list[ToolBinding] = list(), managed_agents: list[str] = list(), parent_supervisor_id: str | None = None)
Bases: BaseEntity
Root aggregate representing a configurable AI agent.
Carries identity + the full versioned configuration. In a future
iteration we may split identity (Agent) from config (AgentVersion)
as discussed in the architectural plan; for the MVP they live together.
execution_pattern
class-attribute
instance-attribute
¶
execution_pattern: ExecutionPatternEnum = REACT
collaboration_pattern
class-attribute
instance-attribute
¶
collaboration_pattern: CollaborationPatternEnum = HIERARCHICAL
engine
class-attribute
instance-attribute
¶
engine: EngineBinding = field(default_factory=EngineBinding)
model
class-attribute
instance-attribute
¶
model: ModelConfig = field(default_factory=ModelConfig)
prompt
class-attribute
instance-attribute
¶
prompt: PromptConfig = field(default_factory=PromptConfig)
memory
class-attribute
instance-attribute
¶
memory: MemoryConfig = field(default_factory=MemoryConfig)
runtime
class-attribute
instance-attribute
¶
runtime: RuntimeConfig = field(default_factory=RuntimeConfig)
tools
class-attribute
instance-attribute
¶
tools: list[ToolBinding] = field(default_factory=list)
managed_agents
class-attribute
instance-attribute
¶
parent_supervisor_id
class-attribute
instance-attribute
¶
AgentEvent
dataclass
¶
AgentInput
dataclass
¶
AgentInput(user_input: str, history: list[Message] = list(), metadata: dict[str, Any] = dict())
AgentOutput
dataclass
¶
AgentOutput(final_response: str, messages: list[Message] = list(), iterations: int = 0, finish_reason: str = 'stop', metadata: dict[str, Any] = dict())
ApprovalDecision
dataclass
¶
ApprovalRequest
dataclass
¶
ApprovalRequest(kind: str, payload: dict[str, Any] = dict(), metadata: dict[str, Any] = dict())
Snapshot of state the human is asked to approve.
BudgetGuardPort
¶
Bases: Protocol
Pre-call gate + post-call charge (adapter delegates to ai-context-budget).
allow
async
¶
allow(ctx: GovernanceContext) -> BudgetVerdict
charge
async
¶
charge(ctx: GovernanceContext, *, prompt_tokens: int, completion_tokens: int) -> None
BudgetVerdict
dataclass
¶
CompiledAgent
dataclass
¶
CompiledAgent(agent: Agent, deps: EngineDependencies, native_object: Any = None)
ContextManagerPort
¶
Conversation
dataclass
¶
Conversation(agent_slug: str = '', user_id: str | None = None, title: str = '', messages: list[Message] = list(), closed: bool = False)
Document
dataclass
¶
Document(text: str, metadata: dict = dict(), id: str = (lambda: f'doc_{hex[:12]}')(), embedding: list[float] = list())
EngineBinding
dataclass
¶
EngineBinding(kind: EngineKindEnum = NATIVE, options: dict[str, Any] = dict())
options
class-attribute
instance-attribute
¶
EngineDependencies
dataclass
¶
EngineDependencies(llm_client: ILLMClient, tool_executor: Any | None = None, extras: dict[str, Any] = dict())
extras
class-attribute
instance-attribute
¶
EvalCase
dataclass
¶
EvalCaseResult
dataclass
¶
EvalReport
dataclass
¶
EvalReport(suite: str, results: list[EvalCaseResult] = list())
EvalRunner
¶
Source code in apogee_ai/application/eval/eval_runner.py
run
async
¶
run(suite: EvalSuite, agent: Agent) -> EvalReport
Source code in apogee_ai/application/eval/eval_runner.py
async def run(self, suite: EvalSuite, agent: Agent) -> EvalReport:
report = EvalReport(suite=suite.name)
for case in suite.cases:
output = await self._exec(agent, case.input)
failed: list[int] = []
for idx, matcher in enumerate(case.matchers):
if not matcher(output):
failed.append(idx)
report.results.append(
EvalCaseResult(
name=case.name,
passed=not failed,
output=output,
failed_matchers=failed,
)
)
return report
ExecutionTrace
dataclass
¶
ExecutionTrace(agent_slug: str = '', conversation_id: str | None = None, user_input: str = '', final_response: str = '', iterations: int = 0, finish_reason: str = 'stop', steps: list[TraceStep] = list(), tokens_prompt: int = 0, tokens_completion: int = 0, cost_usd: float = 0.0, metadata: dict[str, Any] = dict())
GovernanceContext
dataclass
¶
GovernanceDeps
dataclass
¶
GovernanceDeps(tool_guard: ToolGuardPort | None = None, audit: ActionAuditPort | None = None, budget: BudgetGuardPort | None = None, context: ContextManagerPort | None = None)
Optional governance hooks injected via EngineDependencies.extras['governance'].
Every field is optional; a None field disables that hook. An absent
GovernanceDeps (the default) disables all of them.
GuardVerdict
dataclass
¶
GuardrailResult
dataclass
¶
IngestRequest
dataclass
¶
KnowledgeSource
dataclass
¶
KnowledgeSource(name: str = '', description: str = '', vector_store_id: str = '', embedding_model: str = 'text-embedding-3-small', metadata: dict = dict())
Bases: BaseEntity
embedding_model
class-attribute
instance-attribute
¶
LLMRequest
dataclass
¶
LLMRequest(messages: list[Message], model: ModelConfig, stop: list[str] = list(), tools: list[ToolSchema] = list())
tools
class-attribute
instance-attribute
¶
tools: list[ToolSchema] = field(default_factory=list)
LLMResponse
dataclass
¶
LLMResponse(content: str, finish_reason: str = 'stop', prompt_tokens: int = 0, completion_tokens: int = 0, raw: dict | None = None, tool_calls: list[ToolCall] = list())
MemoryConfig
dataclass
¶
MemoryConfig(strategy: MemoryStrategyEnum = SLIDING_WINDOW, context_window: int = 8000, long_term: bool = False, store: str = 'in_memory', session_timeout: int = 3600)
Message
dataclass
¶
Message(role: RoleEnum, content: str, name: str | None = None, tool_calls: list[dict[str, Any]] = list(), created_at: datetime = (lambda: now(utc))())
ModelConfig
dataclass
¶
ModelConfig(provider: LLMProviderEnum = ECHO, model: str = 'echo', temperature: float = 0.7, max_tokens: int = 1024, top_p: float = 1.0, top_k: int | None = None, frequency_penalty: float = 0.0, presence_penalty: float = 0.0, stop_sequences: list[str] = list(), response_format: str = 'text', fallback_model: str | None = None)
stop_sequences
class-attribute
instance-attribute
¶
PromptConfig
dataclass
¶
PromptConfig(system: str = 'You are a helpful assistant.', persona: str | None = None, language: str = 'pt-BR', greeting: str | None = None, template_ref: str | None = None, few_shot_examples: list[dict[str, str]] = list(), output_template: str | None = None)
few_shot_examples
class-attribute
instance-attribute
¶
RuntimeConfig
dataclass
¶
RuntimeConfig(max_iterations: int = 8, timeout_seconds: int = 60, streaming_enabled: bool = False, retry_attempts: int = 2, retry_backoff: str = 'exponential', fallback_agent_id: str | None = None)
Tool
dataclass
¶
Tool(name: str = '', description: str = '', json_schema: dict[str, Any] = dict(), implementation_ref: str = '')
ToolBinding
dataclass
¶
ToolCall
dataclass
¶
ToolGuardPort
¶
Bases: Protocol
Authorizes a tool invocation (adapter delegates to ai-authz).
authorize
async
¶
authorize(ctx: GovernanceContext, *, tool_name: str) -> GuardVerdict
ToolResult
dataclass
¶
ToolSchema
dataclass
¶
TraceStep
dataclass
¶
TraceStep(kind: str, name: str, started_at: datetime = (lambda: now(utc))(), duration_ms: int = 0, input: dict[str, Any] = dict(), output: dict[str, Any] = dict(), is_error: bool = False)
TriggerSpec
dataclass
¶
TriggerSpec(type: TriggerTypeEnum = MANUAL, cron: str | None = None, webhook_path: str | None = None, event_topic: str | None = None, payload_template: str = '', metadata: dict = dict())
WorkerInput
dataclass
¶
WorkerInput(instruction: str, context_messages: list[Message] = list(), metadata: dict[str, Any] = dict())
WorkerResult
dataclass
¶
Other · DTOs¶
AgentOutputDTO
¶
Bases: BaseModel
CreateAgentDTO
¶
Bases: BaseModel
execution_pattern
class-attribute
instance-attribute
¶
execution_pattern: ExecutionPatternEnum = REACT
system_prompt
class-attribute
instance-attribute
¶
ExecuteAgentInputDTO
¶
Bases: BaseModel
ExecuteAgentOutputDTO
¶
Bases: BaseModel
UpdateAgentDTO
¶
Bases: BaseModel
Other · Enums¶
AgentStatusEnum
¶
AgentTypeEnum
¶
Bases: str, Enum
AgentVisibilityEnum
¶
CollaborationPatternEnum
¶
Bases: str, Enum
EngineKindEnum
¶
Bases: str, Enum
ExecutionPatternEnum
¶
Bases: str, Enum
LLMProviderEnum
¶
Bases: str, Enum
MemoryStrategyEnum
¶
Bases: str, Enum
RetrievalStrategyEnum
¶
RoleEnum
¶
ToolChoiceEnum
¶
TriggerTypeEnum
¶
Other · Exceptions¶
AgentAlreadyExistsException
¶
AgentNotFoundException
¶
EngineNotSupportedException
¶
GuardrailViolationException
¶
InvalidAgentConfigException
¶
MaxIterationsExceededException
¶
ToolNotFoundException
¶
Other · Protocols (ports)¶
IAgentEngine
¶
Bases: Protocol
Contract every AI agent engine adapter must implement.
build
async
¶
build(agent: Agent, deps: EngineDependencies) -> CompiledAgent
run
async
¶
run(compiled: CompiledAgent, input: AgentInput) -> AgentOutput
stream
async
¶
stream(compiled: CompiledAgent, input: AgentInput) -> AsyncIterator[AgentEvent]
shutdown
async
¶
shutdown(compiled: CompiledAgent) -> None
IAgentQueryRepository
¶
IConversationRepository
¶
Bases: Protocol
get
async
¶
get(conversation_id: str) -> Conversation | None
list_by_agent
async
¶
list_by_agent(agent_slug: str) -> list[Conversation]
save
async
¶
save(conversation: Conversation) -> Conversation
delete
async
¶
IEmbeddingClient
¶
IExecutionTraceRepository
¶
Bases: Protocol
get
async
¶
get(trace_id: str) -> ExecutionTrace | None
list_by_agent
async
¶
list_by_agent(agent_slug: str) -> list[ExecutionTrace]
save
async
¶
save(trace: ExecutionTrace) -> ExecutionTrace
IGuardrail
¶
Bases: Protocol
check_input
async
¶
check_input(text: str) -> GuardrailResult
check_output
async
¶
check_output(text: str) -> GuardrailResult
IHILApprover
¶
Bases: Protocol
Surface used by the HIL runner to ask a human for go/no-go.
review
async
¶
review(request: ApprovalRequest) -> ApprovalDecision
IHandoffProtocol
¶
Bases: Protocol
build_input
¶
build_input(instruction: str, history: list[Message], target_worker_slug: str) -> WorkerInput
parse_output
¶
parse_output(raw_output: str, source_worker_slug: str) -> WorkerResult
ILLMClient
¶
Bases: Protocol
chat
async
¶
chat(request: LLMRequest) -> LLMResponse
stream
async
¶
stream(request: LLMRequest) -> AsyncIterator[str]
IMemoryStore
¶
IObservabilityEmitter
¶
Bases: Protocol
emit_trace
async
¶
emit_trace(trace: ExecutionTrace) -> None
emit_metric
async
¶
emit_event
async
¶
IToolExecutor
¶
Bases: Protocol
execute
async
¶
execute(call: ToolCall) -> ToolResult
is_registered
¶
IToolQueryRepository
¶
IVectorStore
¶
Other · Use cases¶
AppendMessageUseCase
¶
AppendMessageUseCase(repo: IConversationRepository)
Source code in apogee_ai/application/use_cases/conversations/conversation_use_cases.py
execute
async
¶
execute(conversation_id: str, message: Message) -> Conversation
Source code in apogee_ai/application/use_cases/conversations/conversation_use_cases.py
async def execute(self, conversation_id: str, message: Message) -> Conversation:
conv = await self._repo.get(conversation_id)
if conv is None:
raise KeyError(f"conversation '{conversation_id}' not found")
if conv.closed:
raise ValueError(f"conversation '{conversation_id}' is closed")
conv.append(message)
return await self._repo.save(conv)
CloseConversationUseCase
¶
CloseConversationUseCase(repo: IConversationRepository)
Source code in apogee_ai/application/use_cases/conversations/conversation_use_cases.py
execute
async
¶
execute(conversation_id: str) -> Conversation
Source code in apogee_ai/application/use_cases/conversations/conversation_use_cases.py
CreateAgentUseCase
¶
CreateAgentUseCase(query_repo: IAgentQueryRepository, command_repo: IAgentCommandRepository)
Source code in apogee_ai/application/use_cases/create_agent_use_case.py
execute
async
¶
execute(dto: CreateAgentDTO) -> AgentOutputDTO
Source code in apogee_ai/application/use_cases/create_agent_use_case.py
DeleteAgentUseCase
¶
DeleteAgentUseCase(query_repo: IAgentQueryRepository, command_repo: IAgentCommandRepository)
Source code in apogee_ai/application/use_cases/delete_agent_use_case.py
execute
async
¶
ExecuteAgentUseCase
¶
ExecuteAgentUseCase(query_repo: IAgentQueryRepository, engine_resolver: Callable[[Any], IAgentEngine], llm_resolver: Callable[[Any], ILLMClient], tool_resolver: Callable[[Any], Any] | None = None, guardrail_resolver: Callable[[Any], Any] | None = None, trace_repo: Any | None = None, observability_emitter: Any | None = None)
Source code in apogee_ai/application/use_cases/execute_agent_use_case.py
def __init__(
self,
query_repo: IAgentQueryRepository,
engine_resolver: Callable[[Any], IAgentEngine],
llm_resolver: Callable[[Any], ILLMClient],
tool_resolver: Callable[[Any], Any] | None = None,
guardrail_resolver: Callable[[Any], Any] | None = None,
trace_repo: Any | None = None,
observability_emitter: Any | None = None,
) -> None:
self._query_repo = query_repo
self._engine_resolver = engine_resolver
self._llm_resolver = llm_resolver
self._tool_resolver = tool_resolver
self._guardrail_resolver = guardrail_resolver
self._trace_repo = trace_repo
self._emitter = observability_emitter
execute
async
¶
execute(dto: ExecuteAgentInputDTO) -> ExecuteAgentOutputDTO
Source code in apogee_ai/application/use_cases/execute_agent_use_case.py
async def execute(self, dto: ExecuteAgentInputDTO) -> ExecuteAgentOutputDTO:
agent = await self._query_repo.get_by_slug(dto.slug)
if agent is None:
raise AgentNotFoundException(dto.slug)
guardrails = self._guardrail_resolver(agent) if self._guardrail_resolver else None
user_input = dto.input
if guardrails is not None:
input_check = await guardrails.apply_input(user_input)
user_input = input_check.redacted_text
engine: IAgentEngine = self._engine_resolver(agent)
llm: ILLMClient = self._llm_resolver(agent)
tool_exec = self._tool_resolver(agent) if self._tool_resolver else None
deps = EngineDependencies(llm_client=llm, tool_executor=tool_exec)
compiled = await engine.build(agent, deps)
history = [
Message(role=RoleEnum(m["role"]), content=m["content"])
for m in dto.history
]
agent_input = AgentInput(
user_input=user_input,
history=history,
metadata=dto.metadata,
)
started = time.time()
try:
output = await engine.run(compiled, agent_input)
finally:
await engine.shutdown(compiled)
duration_ms = int((time.time() - started) * 1000)
final = output.final_response
if guardrails is not None:
output_check = await guardrails.apply_output(final)
final = output_check.redacted_text
if self._trace_repo is not None:
trace = ExecutionTrace(
agent_slug=agent.slug,
user_input=dto.input,
final_response=final,
iterations=output.iterations,
finish_reason=output.finish_reason,
metadata={**output.metadata, "duration_ms": duration_ms},
)
trace.add_step(
TraceStep(
kind="agent_run",
name=agent.slug,
duration_ms=duration_ms,
input={"user_input": dto.input},
output={"final_response": final},
)
)
await self._trace_repo.save(trace)
if self._emitter is not None:
await self._emitter.emit_trace(trace)
elif self._emitter is not None:
trace = ExecutionTrace(
agent_slug=agent.slug,
user_input=dto.input,
final_response=final,
iterations=output.iterations,
finish_reason=output.finish_reason,
metadata={**output.metadata, "duration_ms": duration_ms},
)
await self._emitter.emit_trace(trace)
if self._emitter is not None:
await self._emitter.emit_metric(
"agent.iterations", float(output.iterations), {"agent": agent.slug}
)
await self._emitter.emit_metric(
"agent.duration_ms", float(duration_ms), {"agent": agent.slug}
)
return ExecuteAgentOutputDTO(
final_response=final,
iterations=output.iterations,
finish_reason=output.finish_reason,
metadata=output.metadata,
)
GetAgentUseCase
¶
GetAgentUseCase(query_repo: IAgentQueryRepository)
Source code in apogee_ai/application/use_cases/get_agent_use_case.py
execute
async
¶
execute(slug: str) -> AgentOutputDTO
IngestKnowledgeUseCase
¶
IngestKnowledgeUseCase(embedder: IEmbeddingClient, store: IVectorStore)
Source code in apogee_ai/application/use_cases/knowledge/knowledge_use_cases.py
execute
async
¶
execute(req: IngestRequest) -> int
Source code in apogee_ai/application/use_cases/knowledge/knowledge_use_cases.py
async def execute(self, req: IngestRequest) -> int:
embeddings = await self._embedder.embed(req.texts)
metas = req.metadatas or [{} for _ in req.texts]
if len(metas) != len(req.texts):
raise ValueError("metadatas length must match texts length")
docs = [
Document(text=t, metadata=m, embedding=e)
for t, m, e in zip(req.texts, metas, embeddings)
]
return await self._store.upsert(docs)
ListAgentsUseCase
¶
ListAgentsUseCase(query_repo: IAgentQueryRepository)
Source code in apogee_ai/application/use_cases/list_agents_use_case.py
execute
async
¶
execute() -> list[AgentOutputDTO]
QueryKnowledgeUseCase
¶
QueryKnowledgeUseCase(embedder: IEmbeddingClient, store: IVectorStore)
Source code in apogee_ai/application/use_cases/knowledge/knowledge_use_cases.py
execute
async
¶
execute(query: str, top_k: int = 5, threshold: float = 0.0) -> list[RetrievedDocument]
Source code in apogee_ai/application/use_cases/knowledge/knowledge_use_cases.py
StartConversationUseCase
¶
StartConversationUseCase(repo: IConversationRepository)
Source code in apogee_ai/application/use_cases/conversations/conversation_use_cases.py
execute
async
¶
execute(agent_slug: str, user_id: str | None = None, title: str = '') -> Conversation
Source code in apogee_ai/application/use_cases/conversations/conversation_use_cases.py
StreamAgentUseCase
¶
StreamAgentUseCase(query_repo: IAgentQueryRepository, engine_resolver: Callable[[Agent], IAgentEngine], llm_resolver: Callable[[Agent], ILLMClient])
Source code in apogee_ai/application/use_cases/stream_agent_use_case.py
execute
async
¶
execute(dto: ExecuteAgentInputDTO) -> AsyncIterator[AgentEvent]
Source code in apogee_ai/application/use_cases/stream_agent_use_case.py
async def execute(self, dto: ExecuteAgentInputDTO) -> AsyncIterator[AgentEvent]:
agent = await self._repo.get_by_slug(dto.slug)
if agent is None:
raise AgentNotFoundException(slug=dto.slug)
engine = self._resolve_engine(agent)
deps = EngineDependencies(llm_client=self._resolve_llm(agent))
compiled = await engine.build(agent, deps)
async def _gen() -> AsyncIterator[AgentEvent]:
try:
async for event in engine.stream(
compiled, AgentInput(user_input=dto.input)
):
yield event
finally:
await engine.shutdown(compiled)
return _gen()
UpdateAgentUseCase
¶
UpdateAgentUseCase(query_repo: IAgentQueryRepository, command_repo: IAgentCommandRepository)
Source code in apogee_ai/application/use_cases/update_agent_use_case.py
execute
async
¶
execute(slug: str, dto: UpdateAgentDTO) -> AgentOutputDTO
Source code in apogee_ai/application/use_cases/update_agent_use_case.py
async def execute(self, slug: str, dto: UpdateAgentDTO) -> AgentOutputDTO:
agent = await self._query_repo.get_by_slug(slug)
if agent is None:
raise AgentNotFoundException(slug)
if dto.name is not None:
agent.name = dto.name
if dto.description is not None:
agent.description = dto.description
if dto.system_prompt is not None:
agent.prompt.system = dto.system_prompt
if dto.status is not None:
agent.status = dto.status
if dto.tags is not None:
agent.tags = list(dto.tags)
updated = await self._command_repo.update(agent)
return agent_to_output_dto(updated)