-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcode.py
More file actions
69 lines (53 loc) · 2.85 KB
/
Copy pathcode.py
File metadata and controls
69 lines (53 loc) · 2.85 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
"""Multi-Agent Collaboration — separate roles, each with its own system prompt.
Not just three prompts in a row: each agent holds a distinct persona and only
sees what it needs. The researcher doesn't know how to write marketing copy;
the editor doesn't care where the facts came from. Separation is the point.
A coordinator owns the handoffs. Without one you get agents talking past each
other, which is the coordination overhead the pattern is famous for.
"""
from langchain_core.messages import HumanMessage, SystemMessage
from resources.agent import llm
from resources.helper import show_response
BRIEF = "A short launch announcement for a CLI tool that lints Dockerfiles."
# Each agent is a role, not a step. The system prompt is what makes it an
# agent rather than just another call - it carries identity across turns.
AGENTS = {
"researcher": "You are a technical researcher. You gather concrete facts, "
"angles, and specifics. You never write marketing copy - you hand raw "
"material to whoever does. Be terse and factual.",
"writer": "You are a copywriter. You turn raw research into punchy prose. "
"You do not verify facts; you trust your researcher.",
"editor": "You are a ruthless editor. You cut fluff, fix claims that "
"overreach, and enforce the word limit. You return the final text only.",
}
def ask(role, message):
"""Invoke one agent. The system prompt is what gives it its role."""
reply = llm.invoke([SystemMessage(AGENTS[role]), HumanMessage(message)])
print(f"\n{'=' * 60}\nAGENT: {role}\n{'=' * 60}")
show_response(reply)
return reply.content
def coordinate(brief):
"""The coordinator owns every handoff and decides what each agent sees.
Note that each agent gets a scoped view, not the whole conversation. The
writer never sees the brief's phrasing, only the research. The editor
never sees the research, only the draft plus the constraint. Scoping the
context is what keeps roles from blurring back into one generalist.
"""
research = ask("researcher", f"Gather material for this brief: {brief}")
draft = ask("writer", f"Write the announcement from this research:\n\n{research}")
final = ask(
"editor",
# Note: an earlier version asked for "roughly 100 words" and the model
# kept emitting a numbered word-by-word tally instead of prose. A
# structural limit (sentences) gets the same brevity without inviting
# the model to count.
f"Cut this to its strongest four sentences. Drop anything unsupported.\n"
f"Return only the finished announcement prose, nothing else.\n\n{draft}",
)
return final
if __name__ == "__main__":
print(f"BRIEF: {BRIEF}")
final = coordinate(BRIEF)
print(f"\n{'=' * 60}\nFINAL DELIVERABLE\n{'=' * 60}")
print(final)
print(f"\n[coordinator] word count: {len(final.split())}")