Contracts¶
All Pydantic models live in morning_agents/contracts/models.py.
Enums¶
Severity¶
class Severity(str, Enum):
info = "info"
warning = "warning"
action_needed = "action_needed"
AgentStatus¶
class AgentStatus(str, Enum):
success = "success"
partial = "partial"
error = "error"
Core Models¶
Finding¶
A single piece of intel from an agent.
| Field | Type | Description |
|---|---|---|
id |
str |
Unique ID, e.g. "brew-001" |
source_agent |
str |
Agent name that produced this |
category |
str |
Free-form category tag |
severity |
Severity |
info / warning / action_needed |
title |
str |
One-line summary |
detail |
str |
Longer description |
metadata |
dict[str, Any] |
Agent-specific data (always include tool_id) |
timestamp |
AwareDatetime |
UTC timestamp |
Convention: Always include
tool_idinmetadata. Cross-reference rules key on it.
AgentResult¶
One agent's complete output.
| Field | Type | Description |
|---|---|---|
agent_name |
str |
Agent identifier |
agent_display_name |
str |
Display string with emoji |
status |
AgentStatus |
Success / partial / error |
started_at |
AwareDatetime |
When the agent started |
completed_at |
AwareDatetime |
When it finished |
duration_ms |
int |
Wall time in milliseconds |
findings |
list[Finding] |
All findings |
summary |
FindingSummary \| None |
Computed by compute_summary() |
tool_calls |
list[ToolCall] |
MCP and API calls made |
error |
str \| None |
Error message if status is error |
compute_summary() is called by the orchestrator after agent.run() returns.
CrossReference¶
A correlation between findings from different agents.
| Field | Type | Description |
|---|---|---|
id |
str |
Unique ID, e.g. "xref-node-pr-abc12345" |
severity |
Severity |
Severity of the correlation |
title |
str |
One-line description |
detail |
str |
Full explanation |
source_findings |
list[str] |
Finding IDs that triggered this |
source_agents |
list[str] |
Agent names involved |
timestamp |
AwareDatetime |
When the cross-reference was generated |
BriefingOutput¶
The top-level output contract. Everything else is nested here.
| Field | Type | Description |
|---|---|---|
version |
str |
App version |
briefing_id |
str |
e.g. "brief-2026-03-23-091500" |
generated_at |
AwareDatetime |
UTC timestamp |
duration_ms |
int |
Total wall time |
agent_results |
list[AgentResult] |
One per agent |
cross_references |
list[CrossReference] |
Correlated findings |
summary |
BriefingSummary |
Counts and stats |
execution |
ExecutionMeta |
DAG stages, dependency graph, retry counts |
config |
BriefingConfig |
Runtime config snapshot |
Supporting Models¶
ToolCall records a single MCP tool or API call:
class ToolCall(BaseModel):
tool: str # tool name
server: str # "homebrew-mcp", "anthropic", etc.
duration_ms: int
success: bool
FindingSummary stores per-agent finding counts:
class FindingSummary(BaseModel):
total: int
by_severity: dict[str, int]
BriefingSummary stores briefing-level stats:
class BriefingSummary(BaseModel):
agents_run: int
agents_succeeded: int
agents_failed: int
total_findings: int
by_severity: dict[str, int]
mcp_servers_used: int