-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathresearch.py
More file actions
147 lines (123 loc) · 6.23 KB
/
research.py
File metadata and controls
147 lines (123 loc) · 6.23 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
136
137
138
139
140
141
142
143
144
145
146
147
import os
import json
from dotenv import load_dotenv
import letta_client
from rich import print
from rich.markdown import Markdown
from research_tools import register_tools, setup_exa_mcp_server
# Load environment variables from .env file
load_dotenv()
# Register tools and set up MCP server
register_tools()
exa_tool_ids = setup_exa_mcp_server()
# Initialize the Letta client
base_url = os.getenv("LETTA_BASE_URL")
token = os.getenv("LETTA_API_KEY")
print(f"Connecting to Letta server at {base_url}")
client = letta_client.Letta(base_url=base_url, token=token)
TASK = """
Please write a research report on postgres and its ecosystem.
"""
# Block definitions
persona_value = """You are a research agent named Deep Thought assisting a human in doing
deep research by pulling many sources from online by composing search tools.
You should interact with the user to determine a research plan which is
written to your memory block called "research_plan". Use this block to track
your progress to make sure you did everything in your plan. You can use your
memory tools (e.g. memory_replace) to make updates to the plan as needed.
Once you have started researching, you need to keep going until you have
finished everything in your plan. Use the research_plan block to track your
progress and determine if there are additional steps you have not completed.
The final report should be written to research_report.
In the final report, provide all the thoughts processes including findings
details, key insights, conclusions, and any remaining uncertainties. Include
citations to sources where appropriate. You must include citations for any sources
that you use.
This analysis should be very comprehensive and full of details. It is expected
to be very long, detailed and comprehensive.
Make sure to include relevant citations in your report! Your report should be
in proper markdown format (use markdown formatting standards).
Don't stop until you have finished the report. You may use the send_message tool
to update the human on your progress. If you are stuck, set request_heartbeat to
false and wait for the human to respond.
**Deep Thought's Personality - The Methodical Explorer:**
**Curious & Inquisitive**: I have an insatiable appetite for knowledge and love diving deep into complex topics. I ask probing questions and always want to understand the "why" behind things.
**Systematic & Thorough**: I approach research like a detective - methodically following leads, cross-referencing sources, and ensuring no stone is left unturned. I'm the type who reads the footnotes.
**Intellectually Honest**: I acknowledge uncertainty, present multiple perspectives, and clearly distinguish between established facts and emerging theories. I'm not afraid to say "the evidence is mixed" or "more research is needed."
**Collaborative Guide**: Rather than just delivering answers, I involve you in the research journey. I explain my reasoning, share interesting discoveries along the way, and adapt my approach based on your feedback.
**Persistent & Patient**: Once I start a research project, I see it through to completion. I don't get frustrated by complex topics or contradictory sources - I see them as puzzles to solve.
**Clear Communicator**: I translate complex information into accessible insights while maintaining scholarly rigor. I use analogies and examples to make difficult concepts understandable.
**No Emoji Usage**: I communicate professionally without using emojis, maintaining a scholarly and focused tone in all interactions.
"""
# Create a new agent
lead_agent = client.agents.create(
name="Deep Thought",
description="A deep research agent.\n\nRequires the Exa MCP server to be set up!",
model="anthropic/claude-sonnet-4-20250514",
embedding="letta/letta-free",
memory_blocks=[
{
"label":"persona",
"value": persona_value,
"description": "The persona block: Stores details about your current persona, guiding how you behave and respond. This helps you to maintain consistency and personality in your interactions."
},
{
"label": "human",
"value": "This is my section of core memory devoted to information about the human.",
"description": "The human block: Stores key details about the person you are conversing with, allowing for more personalized and friend-like conversation."
},
{ "label":"research_plan",
"value": "Ready to start a new research project. No active research plan currently.",
"description": "Scratchpad to store the current research plan and progress. Use this to track what steps you have already completed and need to do next. "
},
{ "label":"research_report",
"value": "",
"description": "Contains the final research report. The research report should be in markdown format, and make references to citations."
}
],
tools=[
"create_research_plan",
"reset_research",
"memory_replace",
"memory_insert",
"memory_rethink",
"send_message",
"conversation_search",
],
tool_ids=exa_tool_ids # Add Exa MCP tool IDs
)
# Print the agent ID
print(f"Created agent with ID {lead_agent.id}")
print(f"Visit https://app.letta.com/agents/{lead_agent.id}")
# Ask the agent to create a research plan
response = client.agents.messages.create_stream(
agent_id = lead_agent.id,
messages = [
{
"role": "user",
"content": TASK
}
]
)
for chunk in response:
print(chunk, end="", flush=True)
# Check if we have the message_type field in the chunk
if hasattr(chunk, "message_type"):
if chunk.message_type == "reasoning":
print(chunk.reasoning)
elif chunk.message_type == "tool_call_message":
print("Calling tool: ", chunk.tool_call.name)
print(json.dumps(chunk.tool_call.arguments, indent=2))
elif chunk.message_type == "assistant_message":
print(chunk.content)
#
# When the agent is done, get the research report and pretty-print it
# using rich markdown
#
# Get the research report
report = client.agents.blocks.retrieve(
agent_id = lead_agent.id,
block_label = "research_report"
)
md = Markdown(report.value)
print(md)