API Reference¶
Complete reference for all public classes, methods, protocols, and types in cognitia.
Agent Facade (cognitia.agent)¶
Agent¶
High-level facade for interacting with AI agents.
Methods¶
| Method | Signature | Description |
|---|---|---|
query | async query(prompt: str) -> Result | One-shot request. Applies middleware chain, returns collected result |
stream | async stream(prompt: str) -> AsyncIterator[StreamEvent] | Streaming request. Yields events as they arrive |
conversation | conversation(session_id: str \| None = None) -> Conversation | Create multi-turn conversation |
cleanup | async cleanup() -> None | Release resources (runtime, subprocess) |
Properties¶
| Property | Type | Description |
|---|---|---|
config | AgentConfig | The agent's configuration |
runtime_capabilities | RuntimeCapabilities | Capability descriptor of the selected runtime |
Context Manager¶
async with Agent(config) as agent:
result = await agent.query("Hello")
# cleanup called automatically
AgentConfig¶
Frozen dataclass with all agent configuration. Only system_prompt is required.
| Field | Type | Default | Description |
|---|---|---|---|
system_prompt | str | required | System prompt for the agent |
model | str | "sonnet" | Model alias or full ID |
runtime | str | "claude_sdk" | Runtime: "claude_sdk" | "thin" | "deepagents" | "cli" |
tools | tuple[ToolDefinition, ...] | () | Tools from @tool decorator |
middleware | tuple[Middleware, ...] | () | Middleware chain |
mcp_servers | dict[str, Any] | {} | Remote MCP server configs |
hooks | HookRegistry \| None | None | Lifecycle hooks |
max_turns | int \| None | None | Max conversation turns |
max_budget_usd | float \| None | None | Cost budget limit |
output_format | dict[str, Any] \| None | None | JSON Schema for structured output |
cwd | str \| None | None | Working directory for tools |
env | dict[str, str] | {} | Environment variables |
betas | tuple[str, ...] | () | SDK beta features |
sandbox | dict[str, Any] \| None | None | SDK sandbox config |
max_thinking_tokens | int \| None | None | Extended thinking token limit |
fallback_model | str \| None | None | Fallback model on failure |
permission_mode | str | "bypassPermissions" | SDK permission mode |
setting_sources | tuple[str, ...] | () | SDK setting sources |
feature_mode | str | "portable" | "portable" | "hybrid" | "native_first" |
require_capabilities | CapabilityRequirements \| None | None | Fail-fast capability check |
allow_native_features | bool | False | Allow runtime-native features |
native_config | dict[str, Any] | {} | Runtime-specific extra config |
Properties¶
| Property | Type | Description |
|---|---|---|
resolved_model | str | Full model name after alias resolution |
Result¶
Frozen dataclass returned by query() and conversation.say().
| Field | Type | Default | Description |
|---|---|---|---|
text | str | "" | Response text |
session_id | str \| None | None | Session identifier |
total_cost_usd | float \| None | None | Total cost of the request |
usage | dict[str, Any] \| None | None | Token usage (input_tokens, output_tokens) |
structured_output | Any | None | Parsed structured output (if output_format set) |
error | str \| None | None | Error message (if failed) |
| Property | Type | Description |
|---|---|---|
ok | bool | True if error is None |
Conversation¶
Multi-turn dialog management with history tracking.
| Method | Signature | Description |
|---|---|---|
say | async say(prompt: str) -> Result | Send message, get response |
stream | async stream(prompt: str) -> AsyncIterator[StreamEvent] | Stream a response |
close | async close() -> None | Release conversation resources |
| Property | Type | Description |
|---|---|---|
session_id | str | Unique session identifier |
history | list[Message] | Accumulated messages (copy) |
Supports async context manager (async with agent.conversation() as conv).
Runtime behavior: - claude_sdk: warm subprocess, continues conversation natively - thin/deepagents: accumulated messages sent each turn
@tool Decorator¶
Define tools with automatic JSON Schema inference from type hints.
from cognitia import tool
@tool(name="my_tool", description="Description for LLM", schema=None)
async def my_tool(param: str) -> str:
return "result"
| Parameter | Type | Default | Description |
|---|---|---|---|
name | str | required | Unique tool name |
description | str | required | Description for the LLM |
schema | dict[str, Any] \| None | None | Explicit JSON Schema (auto-inferred if None) |
Auto-Inferred Type Mapping¶
| Python Type | JSON Schema Type |
|---|---|
str | "string" |
int | "integer" |
float | "number" |
bool | "boolean" |
T \| None = None | not in required |
ToolDefinition¶
Attached to decorated functions as fn.__tool_definition__:
td = my_tool.__tool_definition__
td.name # "my_tool"
td.description # "Description for LLM"
td.parameters # {"type": "object", "properties": {...}, "required": [...]}
td.handler # async function reference
td.to_tool_spec() # ToolSpec for runtime
Middleware¶
Base class for request/response interceptors.
from cognitia.agent import Middleware
class MyMiddleware(Middleware):
async def before_query(self, prompt: str, config: AgentConfig) -> str:
return prompt # can modify prompt; raise to block
async def after_result(self, result: Result) -> Result:
return result # can modify result
def get_hooks(self) -> HookRegistry | None:
return None # optional lifecycle hooks
Execution order: - before_query: mw1 → mw2 → mw3 (in order) - after_result: mw1 → mw2 → mw3 (in order)
CostTracker¶
from cognitia.agent import CostTracker
tracker = CostTracker(budget_usd=5.0)
tracker.total_cost_usd # float — accumulated cost
tracker.reset() # reset counter
# Raises BudgetExceededError when cost > budget
SecurityGuard¶
from cognitia.agent import SecurityGuard
guard = SecurityGuard(block_patterns=["password", "secret"])
# Blocks tool inputs containing any of the patterns via PreToolUse hook
Stream Events¶
Events yielded by agent.stream() and conversation.stream():
| Type | Attributes | Description |
|---|---|---|
text_delta | text: str | Incremental text from the model |
tool_use_start | tool_name: str, tool_input: dict | Tool call initiated |
tool_use_result | tool_result: str | Tool call completed |
done | text: str, session_id, total_cost_usd, usage, structured_output | Final result |
error | text: str | Error occurred |
Runtime Types (cognitia.runtime.types)¶
Message¶
Universal message for agent runtimes.
| Field | Type | Default | Description |
|---|---|---|---|
role | str | required | "user" | "assistant" | "tool" | "system" |
content | str | required | Message content |
name | str \| None | None | Tool name (for role="tool") |
tool_calls | list[dict] \| None | None | Tool call requests |
metadata | dict \| None | None | Extra metadata |
Methods: to_dict(), Message.from_memory_message(mm).
ToolSpec¶
Tool description for runtime.
from cognitia.runtime.types import ToolSpec
spec = ToolSpec(name="my_tool", description="...", parameters={...}, is_local=True)
| Field | Type | Default | Description |
|---|---|---|---|
name | str | required | Tool name (e.g., "mcp__server__tool") |
description | str | required | Description for the LLM |
parameters | dict[str, Any] | required | JSON Schema |
is_local | bool | False | True for locally executed tools |
RuntimeEvent¶
Unified streaming event from runtimes.
| Type | Data Keys | Description |
|---|---|---|
assistant_delta | text | Streaming text fragment |
status | text | Status message |
tool_call_started | name, correlation_id, args | Tool call began |
tool_call_finished | name, correlation_id, ok, result_summary | Tool call completed |
final | text, new_messages, metrics, session_id, total_cost_usd, usage, structured_output | Turn completed |
error | kind, message, recoverable | Error occurred |
Static factory methods: RuntimeEvent.assistant_delta(text), RuntimeEvent.status(text), RuntimeEvent.tool_call_started(name, args), RuntimeEvent.tool_call_finished(name, correlation_id, ok, summary), RuntimeEvent.final(text, ...), RuntimeEvent.error(error_data).
RuntimeConfig¶
from cognitia.runtime.types import RuntimeConfig
config = RuntimeConfig(
runtime_name="thin", # claude_sdk | thin | deepagents | cli
model="claude-sonnet-4-20250514", # or alias
max_iterations=6, # ReAct loop limit
max_tool_calls=8, # tool calls per turn limit
max_model_retries=2, # retry on bad output
base_url=None, # custom API endpoint
feature_mode="portable", # portable | hybrid | native_first
required_capabilities=None, # CapabilityRequirements
allow_native_features=False, # allow runtime-specific features
native_config={}, # runtime-specific extra config
)
RuntimeErrorData¶
Typed error for runtime events.
| Field | Type | Description |
|---|---|---|
kind | str | Error kind (see below) |
message | str | Human-readable message |
recoverable | bool | Whether the error is recoverable |
details | dict \| None | Extra details |
Error kinds: runtime_crash, bad_model_output, loop_limit, budget_exceeded, mcp_timeout, tool_error, dependency_missing, capability_unsupported.
TurnMetrics¶
| Field | Type | Default | Description |
|---|---|---|---|
latency_ms | int | 0 | Turn latency |
iterations | int | 0 | ReAct iterations |
tool_calls_count | int | 0 | Number of tool calls |
tokens_in | int | 0 | Input tokens |
tokens_out | int | 0 | Output tokens |
model | str | "" | Model used |
Runtime Capabilities (cognitia.runtime.capabilities)¶
RuntimeCapabilities¶
Describes what a runtime supports.
from cognitia.runtime.capabilities import get_runtime_capabilities
caps = get_runtime_capabilities("claude_sdk")
caps.tier # "full"
caps.supports_mcp # True
caps.enabled_flags() # frozenset({"mcp", "resume", "interrupt"})
| Runtime | Tier | MCP | Resume | Interrupt | Provider Override |
|---|---|---|---|---|---|
claude_sdk | full | Yes | Yes | Yes | No |
deepagents | full | No | Yes | No | Yes |
thin | light | Yes | No | No | Yes |
cli | light | No | No | No | No |
CapabilityRequirements¶
Declare what your application needs. Fail-fast validation at config time.
from cognitia.runtime.capabilities import CapabilityRequirements
reqs = CapabilityRequirements(
tier="full",
flags=("mcp", "resume"),
)
Model Registry (cognitia.runtime.types)¶
resolve_model_name¶
from cognitia.runtime.types import resolve_model_name
resolve_model_name("sonnet") # "claude-sonnet-4-20250514"
resolve_model_name("opus") # "claude-opus-4-20250514"
resolve_model_name("haiku") # "claude-haiku-3-20250307"
resolve_model_name("gpt-4o") # "gpt-4o"
resolve_model_name("4o-mini") # "gpt-4o-mini"
resolve_model_name("o3") # "o3"
resolve_model_name("gemini") # "gemini-2.5-pro"
resolve_model_name("r1") # "deepseek-reasoner"
resolve_model_name(None) # default model
Models and aliases are defined in cognitia/runtime/models.yaml.
Memory Protocols (cognitia.memory)¶
All 8 protocols follow ISP (<=5 methods each). Three providers implement all 8: InMemoryMemoryProvider, PostgresMemoryProvider, SQLiteMemoryProvider.
MessageStore¶
class MessageStore(Protocol):
async def save_message(self, user_id: str, topic_id: str, role: str, content: str, tool_calls: list[dict] | None = None) -> None: ...
async def get_messages(self, user_id: str, topic_id: str, limit: int = 50) -> list[MemoryMessage]: ...
async def count_messages(self, user_id: str, topic_id: str) -> int: ...
async def delete_messages_before(self, user_id: str, topic_id: str, keep_last: int = 10) -> int: ...
FactStore¶
class FactStore(Protocol):
async def upsert_fact(self, user_id: str, key: str, value: str, source: str = "") -> None: ...
async def get_facts(self, user_id: str) -> dict[str, str]: ...
GoalStore¶
class GoalStore(Protocol):
async def save_goal(self, user_id: str, topic_id: str, data: dict) -> None: ...
async def get_active_goal(self, user_id: str, topic_id: str) -> dict | None: ...
SummaryStore¶
class SummaryStore(Protocol):
async def save_summary(self, user_id: str, topic_id: str, summary: str, messages_covered: int) -> None: ...
async def get_summary(self, user_id: str, topic_id: str) -> str | None: ...
UserStore¶
class UserStore(Protocol):
async def ensure_user(self, external_id: str) -> str: ...
async def get_user_profile(self, user_id: str) -> dict | None: ...
SessionStateStore¶
class SessionStateStore(Protocol):
async def save_session_state(self, user_id: str, topic_id: str, role_id: str, active_skill_ids: list[str], prompt_hash: str) -> None: ...
async def get_session_state(self, user_id: str, topic_id: str) -> dict | None: ...
PhaseStore¶
class PhaseStore(Protocol):
async def save_phase_state(self, user_id: str, phase: str, notes: str = "") -> None: ...
async def get_phase_state(self, user_id: str) -> dict | None: ...
ToolEventStore¶
class ToolEventStore(Protocol):
async def save_tool_event(self, user_id: str, event_data: dict) -> None: ...
Web Protocols (cognitia.tools.web_protocols)¶
WebProvider¶
class WebProvider(Protocol):
async def fetch(self, url: str) -> str: ...
async def search(self, query: str, max_results: int = 5) -> list[SearchResult]: ...
WebSearchProvider¶
class WebSearchProvider(Protocol):
async def search(self, query: str, max_results: int = 5) -> list[SearchResult]: ...
WebFetchProvider¶
SearchResult¶
See Web Tools for provider implementations.
Hooks (cognitia.hooks)¶
HookRegistry¶
from cognitia.hooks import HookRegistry
registry = HookRegistry()
registry.on_pre_tool_use(callback, matcher="Bash")
registry.on_post_tool_use(callback)
registry.on_stop(callback)
registry.on_user_prompt(callback)
Events: PreToolUse, PostToolUse, Stop, UserPromptSubmit.
SDK Bridge¶
from cognitia.hooks import registry_to_sdk_hooks
sdk_hooks = registry_to_sdk_hooks(registry)
# Pass to Claude Agent SDK options
Observability (cognitia.observability)¶
AgentLogger¶
from cognitia.observability import AgentLogger, configure_logging
configure_logging(level="info", fmt="json")
logger = AgentLogger(component="my_app")
logger.session_created(user_id="u1", topic_id="t1", role_id="coach")
logger.turn_start(user_id="u1", topic_id="t1")
logger.tool_call(tool_name="get_deposits", latency_ms=450)
logger.tool_policy_event(tool_name="Bash", allowed=False, reason="ALWAYS_DENIED")
logger.turn_complete(user_id="u1", topic_id="t1", role_id="coach", prompt_hash="abc123")
Resilience (cognitia.resilience)¶
CircuitBreaker¶
from cognitia.resilience import CircuitBreaker
cb = CircuitBreaker(failure_threshold=3, recovery_timeout_s=60)
if cb.can_execute():
try:
result = await call_service()
cb.record_success()
except Exception:
cb.record_failure()
States: closed (normal) → open (blocking) → half_open (testing recovery).
Bootstrap (cognitia.bootstrap)¶
CognitiaStack¶
from cognitia.bootstrap.stack import CognitiaStack
stack = CognitiaStack.create(
prompts_dir=Path("prompts"),
skills_dir=Path("skills"),
project_root=Path("."),
runtime_config=RuntimeConfig(...),
sandbox_provider=..., # SandboxProvider | None
web_provider=..., # WebProvider | None
todo_provider=..., # TodoProvider | None
memory_bank_provider=..., # MemoryBankProvider | None
plan_manager=..., # PlanManager | None
thinking_enabled=True, # bool
allowed_system_tools={...}, # set[str]
tool_budget_config=..., # ToolBudgetConfig | None
escalate_roles={...}, # set[str]
local_tool_resolver=..., # object | None
)
Returns a CognitiaStack with:
| Attribute | Type | Description |
|---|---|---|
capability_specs | dict[str, ToolSpec] | All capability tools |
capability_executors | dict[str, Callable] | Tool executors |
tool_policy | DefaultToolPolicy | Configured tool policy |
context_builder | DefaultContextBuilder | System prompt builder |
runtime_factory | RuntimeFactory | Runtime factory |
skill_registry | SkillRegistry | Loaded MCP skills |
role_router | KeywordRoleRouter | Role routing |
Policy (cognitia.policy)¶
DefaultToolPolicy¶
from cognitia.policy import DefaultToolPolicy
policy = DefaultToolPolicy(
allowed_system_tools={"bash", "read"},
extra_denied={"dangerous_tool"},
)
result = policy.can_use_tool(tool_name, input_data, state)
Always denied: Bash, Read, Write, Edit, MultiEdit, Glob, Grep, LS, TodoRead, TodoWrite, WebFetch, WebSearch (and snake_case variants).
ToolIdCodec¶
from cognitia.policy import DefaultToolIdCodec
codec = DefaultToolIdCodec()
codec.encode("server", "tool") # "mcp__server__tool"
codec.extract_server("mcp__s__t") # "s"
codec.matches("mcp__s__t", "s") # True
Routing (cognitia.routing)¶
KeywordRoleRouter¶
from cognitia.routing import KeywordRoleRouter
router = KeywordRoleRouter(
default_role="coach",
keyword_map={
"deposit_advisor": ["deposit", "savings"],
"credit_advisor": ["credit", "loan"],
},
)
router.resolve("I want a savings account") # "deposit_advisor"
router.resolve("Hello") # "coach"
router.resolve("...", explicit_role="coach") # "coach" (explicit wins)