-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathagents.py
More file actions
135 lines (102 loc) · 3.3 KB
/
Copy pathagents.py
File metadata and controls
135 lines (102 loc) · 3.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
"""Demo-assistant agents — thin containers (§46, §48).
Logic lives in the Produce classes (`examples/knowledge/produce/`);
here we only declare the consumes/produces contracts.
"""
from reactifact import Agent, Consume, Produce
from reactifact.sources import SourceRef
from .models import (
Answer,
Calculation,
Claim,
Evidence,
ResearchTurn,
SearchDone,
Spreadsheet,
TypedDoc,
UserQuery,
)
from .produce import (
BuildAnswer,
CalculateAggregate,
EvaluateTurn,
ExtractEvidence,
PlannerReply,
PlannerTurn,
ResolveRef,
ResolveTable,
ScoutSources,
VerifyClaims,
)
class Planner(Agent):
"""Router: greeting/direct → ChatReply, research → ResearchTurn."""
name = "planner"
consumes = [Consume(UserQuery)]
produces = [PlannerReply(), PlannerTurn()]
class SearchScout(Agent):
"""Fan-out over sources: refs → SourceRef + search-complete marker."""
name = "search_scout"
consumes = [Consume(ResearchTurn)]
produces = [ScoutSources(), Produce(SearchDone)]
class ResolverAgent(Agent):
"""Lazy materialization of a text link into a typed document."""
name = "resolver"
consumes = [Consume(SourceRef)]
produces = [ResolveRef()]
class TableResolver(Agent):
"""Lazy materialization of a structured ref into a spreadsheet (§29)."""
name = "table_resolver"
consumes = [Consume(SourceRef)]
produces = [ResolveTable()]
class EvidenceBuilder(Agent):
"""Extracts key facts from a document."""
name = "evidence_builder"
consumes = [Consume(TypedDoc)]
produces = [ExtractEvidence()]
class VerifierAgent(Agent):
"""Verifies facts: builds claims with confidence and finds contradictions."""
name = "verifier"
consumes = [Consume(Evidence)]
produces = [VerifyClaims()]
class CalculatorAgent(Agent):
"""Computes over the spreadsheet if the question asks for an aggregate (§29, §67)."""
name = "calculator"
consumes = [Consume(Spreadsheet)]
produces = [CalculateAggregate()]
class ProgressEvaluator(Agent):
"""Deterministic turn overseer: moves statuses forward (§24, §69).
Consumes research lifecycle events: search, documents, evidence, claims,
calculations, the final answer — recomputes the needed status on each one.
"""
name = "progress_evaluator"
consumes = [
Consume(ResearchTurn),
Consume(SourceRef),
Consume(TypedDoc),
Consume(Evidence),
Consume(Claim),
Consume(Spreadsheet),
Consume(Calculation),
Consume(SearchDone),
Consume(Answer),
]
produces = [EvaluateTurn()]
priority = 100
class AnswerBuilder(Agent):
"""Assembles the answer once the turn becomes answerable (§17)."""
name = "answer_builder"
consumes = [Consume.by_field(ResearchTurn, "status", "answerable")]
produces = [BuildAnswer()]
#: The full pipeline, in no particular order — the runtime schedules by
#: reaction to state changes, not by this list's order. Shared by chat.py
#: (console) and web.py (SSE) so the two transports can never drift apart.
AGENTS: list[Agent] = [
Planner(),
SearchScout(),
ResolverAgent(),
TableResolver(),
EvidenceBuilder(),
VerifierAgent(),
CalculatorAgent(),
ProgressEvaluator(),
AnswerBuilder(),
]