@dataclass(frozen=True)
class ChatAgentConfig:
root: Path
max_iterations: int = 10
max_tool_calls: int = 10
max_estimated_cost_cents: int = 0
allow_destructive: bool = False
model: Optional[str] = None
permission_mode: PermissionMode = PermissionMode.PROMPT
memory_limit: int = 5
approved_call_ids: frozenset[str] = frozenset()
enable_subagent: bool = False
max_subagent_depth: int = 1
heartbeat_seconds: float = 0.0
stream: bool = False
on_chunk: Optional[Callable[[str], None]] = None
stream_text_only: bool = True
approval_handler: Optional[ApprovalHandler] = None
budget_prompt_handler: Optional[BudgetPromptHandler] = None
checkpoint_store: Any = None
chat_messages: Optional[list[LLMMessage]] = None
cancel_token: Optional[threading.Event] = None
subagent_manager: Optional[SubagentManager] = None
code_analysis_config: Optional[CodeAnalysisConfig] = None
enable_git_tools: bool = False
skill_search_dirs: Optional[list[str]] = None
skill_source_profile: SkillSourceProfile = 'default'
selected_skills: Optional[frozenset[str]] = None
skill_prompt_mode: str = 'eager'
hook_registry: Optional[HookRegistry] = None
auto_mode_config: Optional[AutoModeConfig] = None
use_approval_store: bool = True
require_plan: bool = False
skip_plan_check: bool = False
validation_profile: Optional[str] = NonePre-conditions: root must be convertible to an absolute Path.
Post-conditions: All fields are immutable (frozen dataclass). root is not automatically resolved in the default constructor — use from_root().
Pre-conditions:
rootis astrorPathpointing to the workspace root (need not exist as a directory).- Any
kwargskey present in the constructor is accepted. Unknown keys raiseTypeError. skill_source_profile='custom'requiresskill_search_dirsto be provided in kwargs.
Post-conditions:
config.rootisPath(root).resolve().- Workspace config file (
.teaagent/config.jsonor.teaagent/config.toml) values are merged as defaults for any field not present inkwargs. memory_limit=Nonein kwargs is treated as "not provided" and falls back to the dataclass default of5.
Raises: ValueError (from ConfigResolver) if config file is malformed.
class ModelDecisionEngine:
def __init__(
self,
*,
adapter: LLMAdapter,
registry: ToolRegistry,
budget: Optional[RunBudget] = None,
project_instructions: str = '',
model: Optional[str] = None,
task_spec: Optional[str] = None,
stream: bool = False,
on_chunk: Optional[Callable[[str], None]] = None,
stream_text_only: bool = True,
chat_messages: Optional[list[LLMMessage]] = None,
skills: Optional[list[SkillContent]] = None,
skill_index: Optional[list[SkillIndexEntry]] = None,
) -> NoneFields:
max_parse_retries: int = 2— Maximum additional LLM calls on JSON parse failure.
Pre-conditions:
contextmust contain key'task'(string).contextmay contain'decision_summary','observations','memories','_cost_cents','_input_tokens','_output_tokens'.
Post-conditions:
- Returns a
Decisionobject (one ofFinalAnswer,ToolCall, or other runner decision types). context['_cost_cents'],context['_input_tokens'],context['_output_tokens']are incremented (not replaced) on each LLM response.- If all retries are exhausted and no fallback applies, returns
FinalAnswerwith content'{"status":"error","action":"wait","reason":"invalid_model_decision_json"}'andmetadata={'decision_fallback': 'invalid_model_decision_json'}.
Raises: Any exception from adapter.complete() propagates unhandled (network errors, auth failures, etc.).
# Preferred positional form
run_chat_agent(
config: ChatAgentConfig,
task: str,
*,
adapter: LLMAdapter | None = None,
audit: Optional[AuditLogger] = None,
registry: Optional[ToolRegistry] = None,
task_spec: Optional[str] = None,
depth: int = 0,
initial_observations: Optional[list[dict[str, Any]]] = None,
initial_context_extra: Optional[dict[str, Any]] = None,
) -> RunResult
# Deprecated keyword-only form (emits DeprecationWarning)
run_chat_agent(
*,
task: str,
adapter: LLMAdapter,
config: ChatAgentConfig,
...
) -> RunResultPre-conditions:
configandtaskmust both be provided.adapteris optional; ifNone, a default adapter is created fromconfig.model.depthmust be>= 0; typically0for top-level calls, incremented for subagent calls.- If
config.skill_source_profile == 'custom',config.skill_search_dirsmust be non-empty.
Post-conditions:
- Returns a
RunResultwith fields:run_id,status,final_answer,iterations,tool_calls,cost_cents,input_tokens,output_tokens,error_message,metadata. - Heartbeat (if configured) is unconditionally stopped before returning.
- If status is
'completed'andfinal_answeris non-None, an auto-curated memory entry may be written toMemoryCatalog.
Raises:
TypeErrorif bothconfigandtaskare missing.ValueErrorifskill_source_profile='custom'andskill_search_dirsis empty.
def with_memories(context: dict, memories: list[dict]) -> dictPre-conditions: context is any dict; memories is a list (may be empty).
Post-conditions:
- If
memoriesis empty, returnscontextunchanged (same object). - If non-empty, returns a shallow copy of
contextwithcontext['memories'] = memories.
def register_subagent_tool(
registry: ToolRegistry,
*,
adapter: LLMAdapter,
config: ChatAgentConfig,
depth: int,
) -> NonePre-conditions: depth >= 0. registry must be a valid ToolRegistry instance.
Post-conditions: Subagent tools are registered on registry. If config.code_analysis_config is set, code analysis tools are also registered.
| Field | Type | Description |
|---|---|---|
run_id |
str |
Unique hex run identifier |
status |
str |
'completed', 'pending_approval', 'failed:model_logic', 'failed:permission', 'failed:system', 'failed:transient' |
final_answer |
Optional[FinalAnswer] |
Agent's final answer on success |
iterations |
int |
Number of LLM calls made |
tool_calls |
int |
Total tool invocations |
cost_cents |
float |
Estimated cost in US cents |
input_tokens |
int |
Total input tokens consumed |
output_tokens |
int |
Total output tokens generated |
error_message |
Optional[str] |
Error description on failure |
metadata |
dict |
Arbitrary metadata from runner |
| Config key | Maps to field |
|---|---|
permission_mode |
permission_mode |
max_iterations |
max_iterations |
max_tool_calls |
max_tool_calls |
model |
model |
code_analysis_enabled |
code_analysis_config |
git_tools_enabled |
enable_git_tools |
github_tools_enabled |
enable_github_tools |
skill_search_dirs |
skill_search_dirs |
skill_source_profile |
skill_source_profile |