intentkit 0.7.5.dev17__py3-none-any.whl → 0.7.5.dev19__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of intentkit might be problematic. Click here for more details.

intentkit/__init__.py CHANGED
@@ -3,7 +3,7 @@
3
3
  A powerful platform for building AI agents with blockchain and cryptocurrency capabilities.
4
4
  """
5
5
 
6
- __version__ = "0.7.5-dev17"
6
+ __version__ = "0.7.5-dev19"
7
7
  __author__ = "hyacinthus"
8
8
  __email__ = "hyacinthus@gmail.com"
9
9
 
@@ -1,6 +1,5 @@
1
- import asyncio
2
1
  from enum import Enum
3
- from typing import Any, Dict, NotRequired, Optional
2
+ from typing import Any, Callable, Dict, NotRequired, Optional
4
3
 
5
4
  from langgraph.prebuilt.chat_agent_executor import AgentState as BaseAgentState
6
5
  from pydantic import BaseModel
@@ -29,6 +28,7 @@ class AgentState(BaseAgentState):
29
28
 
30
29
  class AgentContext(BaseModel):
31
30
  agent_id: str
31
+ get_agent: Callable[[], Agent]
32
32
  chat_id: str
33
33
  user_id: Optional[str] = None
34
34
  app_id: Optional[str] = None
@@ -38,4 +38,4 @@ class AgentContext(BaseModel):
38
38
 
39
39
  @property
40
40
  def agent(self) -> Agent:
41
- return asyncio.run(Agent.get(self.agent_id))
41
+ return self.get_agent()
@@ -1,5 +1,3 @@
1
- # app/config.py
2
- import asyncio
3
1
  import json
4
2
  import logging
5
3
  import os
@@ -11,9 +9,6 @@ from intentkit.utils.logging import setup_logging
11
9
  from intentkit.utils.s3 import init_s3
12
10
  from intentkit.utils.slack_alert import init_slack
13
11
 
14
- # hack for cdp bug
15
- asyncio.set_event_loop_policy(asyncio.DefaultEventLoopPolicy())
16
-
17
12
  # Load environment variables from .env file
18
13
  load_dotenv()
19
14
 
intentkit/core/engine.py CHANGED
@@ -21,6 +21,7 @@ from typing import Optional, Tuple
21
21
 
22
22
  import sqlalchemy
23
23
  from epyxid import XID
24
+ from langchain_core.language_models import BaseChatModel
24
25
  from langchain_core.messages import (
25
26
  BaseMessage,
26
27
  HumanMessage,
@@ -29,6 +30,7 @@ from langchain_core.tools import BaseTool
29
30
  from langgraph.errors import GraphRecursionError
30
31
  from langgraph.graph.state import CompiledStateGraph
31
32
  from langgraph.prebuilt import create_react_agent
33
+ from langgraph.runtime import Runtime
32
34
  from sqlalchemy import func, update
33
35
  from sqlalchemy.exc import SQLAlchemyError
34
36
 
@@ -63,15 +65,13 @@ logger = logging.getLogger(__name__)
63
65
 
64
66
  # Global variable to cache all agent executors
65
67
  _agents: dict[str, CompiledStateGraph] = {}
66
- _private_agents: dict[str, CompiledStateGraph] = {}
67
68
 
68
69
  # Global dictionaries to cache agent update times
69
70
  _agents_updated: dict[str, datetime] = {}
70
- _private_agents_updated: dict[str, datetime] = {}
71
71
 
72
72
 
73
- async def create_agent(agent: Agent, is_private: bool = False) -> CompiledStateGraph:
74
- """Create an AI agent with specified configuration and tools.
73
+ async def build_agent(agent: Agent, agent_data: AgentData) -> CompiledStateGraph:
74
+ """Build an AI agent with specified configuration and tools.
75
75
 
76
76
  This function:
77
77
  1. Initializes LLM with specified model
@@ -81,13 +81,12 @@ async def create_agent(agent: Agent, is_private: bool = False) -> CompiledStateG
81
81
 
82
82
  Args:
83
83
  agent (Agent): Agent configuration object
84
+ agent_data (AgentData): Agent data object
84
85
  is_private (bool, optional): Flag indicating whether the agent is private. Defaults to False.
85
- has_search (bool, optional): Flag indicating whether to include search tools. Defaults to False.
86
86
 
87
87
  Returns:
88
88
  CompiledStateGraph: Initialized LangChain agent
89
89
  """
90
- agent_data = await AgentData.get(agent.id)
91
90
 
92
91
  # Create the LLM model instance
93
92
  llm_model = await create_llm_model(
@@ -108,6 +107,7 @@ async def create_agent(agent: Agent, is_private: bool = False) -> CompiledStateG
108
107
 
109
108
  # ==== Load skills
110
109
  tools: list[BaseTool | dict] = []
110
+ private_tools: list[BaseTool | dict] = []
111
111
 
112
112
  if agent.skills:
113
113
  for k, v in agent.skills.items():
@@ -116,11 +116,18 @@ async def create_agent(agent: Agent, is_private: bool = False) -> CompiledStateG
116
116
  try:
117
117
  skill_module = importlib.import_module(f"intentkit.skills.{k}")
118
118
  if hasattr(skill_module, "get_skills"):
119
+ # all
119
120
  skill_tools = await skill_module.get_skills(
120
- v, is_private, agent_store, agent_id=agent.id
121
+ v, False, agent_store, agent_id=agent.id
121
122
  )
122
123
  if skill_tools and len(skill_tools) > 0:
123
124
  tools.extend(skill_tools)
125
+ # private
126
+ skill_private_tools = await skill_module.get_skills(
127
+ v, True, agent_store, agent_id=agent.id
128
+ )
129
+ if skill_private_tools and len(skill_private_tools) > 0:
130
+ private_tools.extend(skill_private_tools)
124
131
  else:
125
132
  logger.error(f"Skill {k} does not have get_skills function")
126
133
  except ImportError as e:
@@ -128,23 +135,33 @@ async def create_agent(agent: Agent, is_private: bool = False) -> CompiledStateG
128
135
 
129
136
  # filter the duplicate tools
130
137
  tools = list({tool.name: tool for tool in tools}.values())
138
+ private_tools = list({tool.name: tool for tool in private_tools}.values())
131
139
 
132
140
  # Add search tools if requested
133
141
  if (
134
- llm_model.info.provider == LLMProvider.OPENAI
135
- and llm_model.info.supports_search
136
- and not agent.model.startswith(
137
- "gpt-5"
138
- ) # tmp disable gpt-5 search since package bugs
142
+ llm_model.info.provider == LLMProvider.OPENAI and llm_model.info.supports_search
143
+ # and not agent.model.startswith(
144
+ # "gpt-5"
145
+ # ) # tmp disable gpt-5 search since package bugs
139
146
  ):
140
147
  tools.append({"type": "web_search_preview"})
148
+ private_tools.append({"type": "web_search_preview"})
141
149
 
142
150
  # Create the formatted_prompt function using the refactored prompt module
143
151
  formatted_prompt = create_formatted_prompt_function(agent, agent_data)
144
152
 
153
+ # bind tools to llm
154
+ def select_model(
155
+ state: AgentState, runtime: Runtime[AgentContext]
156
+ ) -> BaseChatModel:
157
+ context = runtime.context
158
+ if context.is_private:
159
+ return llm.bind_tools(private_tools)
160
+ return llm.bind_tools(tools)
161
+
145
162
  for tool in tools:
146
163
  logger.info(
147
- f"[{agent.id}{'-private' if is_private else ''}] loaded tool: {tool.name if isinstance(tool, BaseTool) else tool}"
164
+ f"[{agent.id}] loaded tool: {tool.name if isinstance(tool, BaseTool) else tool}"
148
165
  )
149
166
 
150
167
  # Pre model hook
@@ -157,7 +174,7 @@ async def create_agent(agent: Agent, is_private: bool = False) -> CompiledStateG
157
174
 
158
175
  # Create ReAct Agent using the LLM and CDP Agentkit tools.
159
176
  executor = create_react_agent(
160
- model=llm,
177
+ model=select_model,
161
178
  tools=tools,
162
179
  prompt=formatted_prompt,
163
180
  pre_model_hook=pre_model_hook,
@@ -172,7 +189,23 @@ async def create_agent(agent: Agent, is_private: bool = False) -> CompiledStateG
172
189
  return executor
173
190
 
174
191
 
175
- async def initialize_agent(aid, is_private=False):
192
+ async def create_agent(agent: Agent) -> CompiledStateGraph:
193
+ """Create an AI agent with specified configuration and tools.
194
+
195
+ This function maintains backward compatibility by calling build_agent internally.
196
+
197
+ Args:
198
+ agent (Agent): Agent configuration object
199
+ is_private (bool, optional): Flag indicating whether the agent is private. Defaults to False.
200
+
201
+ Returns:
202
+ CompiledStateGraph: Initialized LangChain agent
203
+ """
204
+ agent_data = await AgentData.get(agent.id)
205
+ return await build_agent(agent, agent_data)
206
+
207
+
208
+ async def initialize_agent(aid):
176
209
  """Initialize an AI agent with specified configuration and tools.
177
210
 
178
211
  This function:
@@ -198,47 +231,34 @@ async def initialize_agent(aid, is_private=False):
198
231
  )
199
232
 
200
233
  # Create the agent using the new create_agent function
201
- executor = await create_agent(agent, is_private)
234
+ executor = await create_agent(agent)
202
235
 
203
236
  # Cache the agent executor
204
- if is_private:
205
- _private_agents[aid] = executor
206
- _private_agents_updated[aid] = agent.updated_at
207
- else:
208
- _agents[aid] = executor
209
- _agents_updated[aid] = agent.updated_at
237
+ _agents[aid] = executor
238
+ _agents_updated[aid] = agent.deployed_at if agent.deployed_at else agent.updated_at
210
239
 
211
240
 
212
- async def agent_executor(
213
- agent_id: str, is_private: bool
214
- ) -> Tuple[CompiledStateGraph, float]:
241
+ async def agent_executor(agent_id: str) -> Tuple[CompiledStateGraph, float]:
215
242
  start = time.perf_counter()
216
243
  agent = await Agent.get(agent_id)
217
244
  if not agent:
218
245
  raise IntentKitAPIError(
219
246
  status_code=404, key="AgentNotFound", message="Agent not found"
220
247
  )
221
- agents = _private_agents if is_private else _agents
222
- agents_updated = _private_agents_updated if is_private else _agents_updated
223
-
248
+ updated_at = agent.deployed_at if agent.deployed_at else agent.updated_at
224
249
  # Check if agent needs reinitialization due to updates
225
250
  needs_reinit = False
226
- if agent_id in agents:
227
- if (
228
- agent_id not in agents_updated
229
- or agent.updated_at != agents_updated[agent_id]
230
- ):
251
+ if agent_id in _agents:
252
+ if agent_id not in _agents_updated or updated_at != _agents_updated[agent_id]:
231
253
  needs_reinit = True
232
- logger.info(
233
- f"Reinitializing agent {agent_id} due to updates, private mode: {is_private}"
234
- )
254
+ logger.info(f"Reinitializing agent {agent_id} due to updates")
235
255
 
236
256
  # cold start or needs reinitialization
237
257
  cold_start_cost = 0.0
238
- if (agent_id not in agents) or needs_reinit:
239
- await initialize_agent(agent_id, is_private)
258
+ if (agent_id not in _agents) or needs_reinit:
259
+ await initialize_agent(agent_id)
240
260
  cold_start_cost = time.perf_counter() - start
241
- return agents[agent_id], cold_start_cost
261
+ return _agents[agent_id], cold_start_cost
242
262
 
243
263
 
244
264
  async def stream_agent(message: ChatMessageCreate):
@@ -257,24 +277,30 @@ async def stream_agent(message: ChatMessageCreate):
257
277
  Yields:
258
278
  ChatMessage: Individual response messages including timing information
259
279
  """
280
+ agent = await Agent.get(message.agent_id)
281
+ executor, cold_start_cost = await agent_executor(message.agent_id)
282
+ message.cold_start_cost = cold_start_cost
283
+ async for chat_message in stream_agent_raw(message, agent, executor):
284
+ yield chat_message
285
+
286
+
287
+ async def stream_agent_raw(
288
+ message: ChatMessageCreate, agent: Agent, executor: CompiledStateGraph
289
+ ):
260
290
  start = time.perf_counter()
261
291
  # make sure reply_to is set
262
292
  message.reply_to = message.id
263
293
 
264
294
  # save input message first
265
- input = await message.save()
266
-
267
- # agent
268
- agent = await Agent.get(input.agent_id)
295
+ user_message = await message.save()
269
296
 
270
- # model
271
297
  model = await LLMModelInfo.get(agent.model)
272
298
 
273
299
  payment_enabled = config.payment_enabled
274
300
 
275
301
  # check user balance
276
302
  if payment_enabled:
277
- if not input.user_id or not agent.owner:
303
+ if not user_message.user_id or not agent.owner:
278
304
  raise IntentKitAPIError(
279
305
  500,
280
306
  "PaymentError",
@@ -285,20 +311,20 @@ async def stream_agent(message: ChatMessageCreate):
285
311
  if owner and agent.fee_percentage > 100 + owner.nft_count * 10:
286
312
  error_message_create = await ChatMessageCreate.from_system_message(
287
313
  SystemMessageType.SERVICE_FEE_ERROR,
288
- agent_id=input.agent_id,
289
- chat_id=input.chat_id,
290
- user_id=input.user_id,
291
- author_id=input.agent_id,
292
- thread_type=input.author_type,
293
- reply_to=input.id,
314
+ agent_id=user_message.agent_id,
315
+ chat_id=user_message.chat_id,
316
+ user_id=user_message.user_id,
317
+ author_id=user_message.agent_id,
318
+ thread_type=user_message.author_type,
319
+ reply_to=user_message.id,
294
320
  time_cost=time.perf_counter() - start,
295
321
  )
296
322
  error_message = await error_message_create.save()
297
323
  yield error_message
298
324
  return
299
325
  # payer
300
- payer = input.user_id
301
- if input.author_type in [
326
+ payer = user_message.user_id
327
+ if user_message.author_type in [
302
328
  AuthorType.TELEGRAM,
303
329
  AuthorType.TWITTER,
304
330
  AuthorType.API,
@@ -321,12 +347,12 @@ async def stream_agent(message: ChatMessageCreate):
321
347
  if quota and quota.free_income_daily > 24000:
322
348
  error_message_create = await ChatMessageCreate.from_system_message(
323
349
  SystemMessageType.DAILY_USAGE_LIMIT_EXCEEDED,
324
- agent_id=input.agent_id,
325
- chat_id=input.chat_id,
326
- user_id=input.user_id,
327
- author_id=input.agent_id,
328
- thread_type=input.author_type,
329
- reply_to=input.id,
350
+ agent_id=user_message.agent_id,
351
+ chat_id=user_message.chat_id,
352
+ user_id=user_message.user_id,
353
+ author_id=user_message.agent_id,
354
+ thread_type=user_message.author_type,
355
+ reply_to=user_message.id,
330
356
  time_cost=time.perf_counter() - start,
331
357
  )
332
358
  error_message = await error_message_create.save()
@@ -339,12 +365,12 @@ async def stream_agent(message: ChatMessageCreate):
339
365
  if not user_account.has_sufficient_credits(avg_count):
340
366
  error_message_create = await ChatMessageCreate.from_system_message(
341
367
  SystemMessageType.INSUFFICIENT_BALANCE,
342
- agent_id=input.agent_id,
343
- chat_id=input.chat_id,
344
- user_id=input.user_id,
345
- author_id=input.agent_id,
346
- thread_type=input.author_type,
347
- reply_to=input.id,
368
+ agent_id=user_message.agent_id,
369
+ chat_id=user_message.chat_id,
370
+ user_id=user_message.user_id,
371
+ author_id=user_message.agent_id,
372
+ thread_type=user_message.author_type,
373
+ reply_to=user_message.id,
348
374
  time_cost=time.perf_counter() - start,
349
375
  )
350
376
  error_message = await error_message_create.save()
@@ -352,23 +378,22 @@ async def stream_agent(message: ChatMessageCreate):
352
378
  return
353
379
 
354
380
  is_private = False
355
- if input.user_id == agent.owner:
381
+ if user_message.user_id == agent.owner:
356
382
  is_private = True
357
383
 
358
- executor, cold_start_cost = await agent_executor(input.agent_id, is_private)
359
- last = start + cold_start_cost
384
+ last = start
360
385
 
361
386
  # Extract images from attachments
362
387
  image_urls = []
363
- if input.attachments:
388
+ if user_message.attachments:
364
389
  image_urls = [
365
390
  att["url"]
366
- for att in input.attachments
391
+ for att in user_message.attachments
367
392
  if "type" in att and att["type"] == "image" and "url" in att
368
393
  ]
369
394
 
370
395
  # Process input message to handle @skill patterns
371
- input_message = await explain_prompt(input.message)
396
+ input_message = await explain_prompt(user_message.message)
372
397
 
373
398
  # super mode
374
399
  recursion_limit = 30
@@ -424,7 +449,7 @@ async def stream_agent(message: ChatMessageCreate):
424
449
  ]
425
450
 
426
451
  # stream config
427
- thread_id = f"{input.agent_id}-{input.chat_id}"
452
+ thread_id = f"{user_message.agent_id}-{user_message.chat_id}"
428
453
  stream_config = {
429
454
  "configurable": {
430
455
  "thread_id": thread_id,
@@ -432,12 +457,16 @@ async def stream_agent(message: ChatMessageCreate):
432
457
  "recursion_limit": recursion_limit,
433
458
  }
434
459
 
460
+ def get_agent() -> Agent:
461
+ return agent
462
+
435
463
  context = AgentContext(
436
- agent_id=input.agent_id,
437
- chat_id=input.chat_id,
438
- user_id=input.user_id,
439
- app_id=input.app_id,
440
- entrypoint=input.author_type,
464
+ agent_id=user_message.agent_id,
465
+ get_agent=get_agent,
466
+ chat_id=user_message.chat_id,
467
+ user_id=user_message.user_id,
468
+ app_id=user_message.app_id,
469
+ entrypoint=user_message.author_type,
441
470
  is_private=is_private,
442
471
  payer=payer if payment_enabled else None,
443
472
  )
@@ -474,14 +503,14 @@ async def stream_agent(message: ChatMessageCreate):
474
503
  # agent message
475
504
  chat_message_create = ChatMessageCreate(
476
505
  id=str(XID()),
477
- agent_id=input.agent_id,
478
- chat_id=input.chat_id,
479
- user_id=input.user_id,
480
- author_id=input.agent_id,
506
+ agent_id=user_message.agent_id,
507
+ chat_id=user_message.chat_id,
508
+ user_id=user_message.user_id,
509
+ author_id=user_message.agent_id,
481
510
  author_type=AuthorType.AGENT,
482
511
  model=agent.model,
483
- thread_type=input.author_type,
484
- reply_to=input.id,
512
+ thread_type=user_message.author_type,
513
+ reply_to=user_message.id,
485
514
  message=content,
486
515
  input_tokens=(
487
516
  msg.usage_metadata.get("input_tokens", 0)
@@ -496,9 +525,6 @@ async def stream_agent(message: ChatMessageCreate):
496
525
  time_cost=this_time - last,
497
526
  )
498
527
  last = this_time
499
- if cold_start_cost > 0:
500
- chat_message_create.cold_start_cost = cold_start_cost
501
- cold_start_cost = 0
502
528
  # handle message and payment in one transaction
503
529
  async with get_session() as session:
504
530
  # payment
@@ -519,7 +545,7 @@ async def stream_agent(message: ChatMessageCreate):
519
545
  for tool_output in tool_outputs:
520
546
  if tool_output.get("type") == "web_search_call":
521
547
  logger.info(
522
- f"[{input.agent_id}] Found web_search_call in additional_kwargs"
548
+ f"[{user_message.agent_id}] Found web_search_call in additional_kwargs"
523
549
  )
524
550
  amount += 35
525
551
  break
@@ -527,11 +553,13 @@ async def stream_agent(message: ChatMessageCreate):
527
553
  session,
528
554
  payer,
529
555
  chat_message_create.id,
530
- input.id,
556
+ user_message.id,
531
557
  amount,
532
558
  agent,
533
559
  )
534
- logger.info(f"[{input.agent_id}] expense message: {amount}")
560
+ logger.info(
561
+ f"[{user_message.agent_id}] expense message: {amount}"
562
+ )
535
563
  chat_message_create.credit_event_id = credit_event.id
536
564
  chat_message_create.credit_cost = credit_event.total_amount
537
565
  chat_message = await chat_message_create.save_in_session(
@@ -582,14 +610,14 @@ async def stream_agent(message: ChatMessageCreate):
582
610
  break
583
611
  skill_message_create = ChatMessageCreate(
584
612
  id=str(XID()),
585
- agent_id=input.agent_id,
586
- chat_id=input.chat_id,
587
- user_id=input.user_id,
588
- author_id=input.agent_id,
613
+ agent_id=user_message.agent_id,
614
+ chat_id=user_message.chat_id,
615
+ user_id=user_message.user_id,
616
+ author_id=user_message.agent_id,
589
617
  author_type=AuthorType.SKILL,
590
618
  model=agent.model,
591
- thread_type=input.author_type,
592
- reply_to=input.id,
619
+ thread_type=user_message.author_type,
620
+ reply_to=user_message.id,
593
621
  message="",
594
622
  skill_calls=skill_calls,
595
623
  attachments=cached_attachments,
@@ -610,9 +638,6 @@ async def stream_agent(message: ChatMessageCreate):
610
638
  time_cost=this_time - last,
611
639
  )
612
640
  last = this_time
613
- if cold_start_cost > 0:
614
- skill_message_create.cold_start_cost = cold_start_cost
615
- cold_start_cost = 0
616
641
  # save message and credit in one transaction
617
642
  async with get_session() as session:
618
643
  if payment_enabled:
@@ -626,7 +651,7 @@ async def stream_agent(message: ChatMessageCreate):
626
651
  session,
627
652
  payer,
628
653
  skill_message_create.id,
629
- input.id,
654
+ user_message.id,
630
655
  message_amount,
631
656
  agent,
632
657
  )
@@ -644,7 +669,7 @@ async def stream_agent(message: ChatMessageCreate):
644
669
  session,
645
670
  payer,
646
671
  skill_message_create.id,
647
- input.id,
672
+ user_message.id,
648
673
  skill_call["id"],
649
674
  skill_call["name"],
650
675
  agent,
@@ -652,7 +677,7 @@ async def stream_agent(message: ChatMessageCreate):
652
677
  skill_call["credit_event_id"] = payment_event.id
653
678
  skill_call["credit_cost"] = payment_event.total_amount
654
679
  logger.info(
655
- f"[{input.agent_id}] skill payment: {skill_call}"
680
+ f"[{user_message.agent_id}] skill payment: {skill_call}"
656
681
  )
657
682
  skill_message_create.skill_calls = skill_calls
658
683
  skill_message = await skill_message_create.save_in_session(session)
@@ -678,36 +703,31 @@ async def stream_agent(message: ChatMessageCreate):
678
703
  content = msg.content[0]
679
704
  post_model_message_create = ChatMessageCreate(
680
705
  id=str(XID()),
681
- agent_id=input.agent_id,
682
- chat_id=input.chat_id,
683
- user_id=input.user_id,
684
- author_id=input.agent_id,
706
+ agent_id=user_message.agent_id,
707
+ chat_id=user_message.chat_id,
708
+ user_id=user_message.user_id,
709
+ author_id=user_message.agent_id,
685
710
  author_type=AuthorType.AGENT,
686
711
  model=agent.model,
687
- thread_type=input.author_type,
688
- reply_to=input.id,
712
+ thread_type=user_message.author_type,
713
+ reply_to=user_message.id,
689
714
  message=content,
690
715
  input_tokens=0,
691
716
  output_tokens=0,
692
717
  time_cost=this_time - last,
693
718
  )
694
719
  last = this_time
695
- if cold_start_cost > 0:
696
- post_model_message_create.cold_start_cost = (
697
- cold_start_cost
698
- )
699
- cold_start_cost = 0
700
720
  post_model_message = await post_model_message_create.save()
701
721
  yield post_model_message
702
722
  error_message_create = (
703
723
  await ChatMessageCreate.from_system_message(
704
724
  SystemMessageType.INSUFFICIENT_BALANCE,
705
- agent_id=input.agent_id,
706
- chat_id=input.chat_id,
707
- user_id=input.user_id,
708
- author_id=input.agent_id,
709
- thread_type=input.author_type,
710
- reply_to=input.id,
725
+ agent_id=user_message.agent_id,
726
+ chat_id=user_message.chat_id,
727
+ user_id=user_message.user_id,
728
+ author_id=user_message.agent_id,
729
+ thread_type=user_message.author_type,
730
+ reply_to=user_message.id,
711
731
  time_cost=0,
712
732
  )
713
733
  )
@@ -727,12 +747,12 @@ async def stream_agent(message: ChatMessageCreate):
727
747
  )
728
748
  error_message_create = await ChatMessageCreate.from_system_message(
729
749
  SystemMessageType.AGENT_INTERNAL_ERROR,
730
- agent_id=input.agent_id,
731
- chat_id=input.chat_id,
732
- user_id=input.user_id,
733
- author_id=input.agent_id,
734
- thread_type=input.author_type,
735
- reply_to=input.id,
750
+ agent_id=user_message.agent_id,
751
+ chat_id=user_message.chat_id,
752
+ user_id=user_message.user_id,
753
+ author_id=user_message.agent_id,
754
+ thread_type=user_message.author_type,
755
+ reply_to=user_message.id,
736
756
  time_cost=time.perf_counter() - start,
737
757
  )
738
758
  error_message = await error_message_create.save()
@@ -742,16 +762,16 @@ async def stream_agent(message: ChatMessageCreate):
742
762
  error_traceback = traceback.format_exc()
743
763
  logger.error(
744
764
  f"reached recursion limit: {str(e)}\n{error_traceback}",
745
- extra={"thread_id": thread_id, "agent_id": input.agent_id},
765
+ extra={"thread_id": thread_id, "agent_id": user_message.agent_id},
746
766
  )
747
767
  error_message_create = await ChatMessageCreate.from_system_message(
748
768
  SystemMessageType.STEP_LIMIT_EXCEEDED,
749
- agent_id=input.agent_id,
750
- chat_id=input.chat_id,
751
- user_id=input.user_id,
752
- author_id=input.agent_id,
753
- thread_type=input.author_type,
754
- reply_to=input.id,
769
+ agent_id=user_message.agent_id,
770
+ chat_id=user_message.chat_id,
771
+ user_id=user_message.user_id,
772
+ author_id=user_message.agent_id,
773
+ thread_type=user_message.author_type,
774
+ reply_to=user_message.id,
755
775
  time_cost=time.perf_counter() - start,
756
776
  )
757
777
  error_message = await error_message_create.save()
@@ -761,21 +781,21 @@ async def stream_agent(message: ChatMessageCreate):
761
781
  error_traceback = traceback.format_exc()
762
782
  logger.error(
763
783
  f"failed to execute agent: {str(e)}\n{error_traceback}",
764
- extra={"thread_id": thread_id, "agent_id": input.agent_id},
784
+ extra={"thread_id": thread_id, "agent_id": user_message.agent_id},
765
785
  )
766
786
  error_message_create = await ChatMessageCreate.from_system_message(
767
787
  SystemMessageType.AGENT_INTERNAL_ERROR,
768
- agent_id=input.agent_id,
769
- chat_id=input.chat_id,
770
- user_id=input.user_id,
771
- author_id=input.agent_id,
772
- thread_type=input.author_type,
773
- reply_to=input.id,
788
+ agent_id=user_message.agent_id,
789
+ chat_id=user_message.chat_id,
790
+ user_id=user_message.user_id,
791
+ author_id=user_message.agent_id,
792
+ thread_type=user_message.author_type,
793
+ reply_to=user_message.id,
774
794
  time_cost=time.perf_counter() - start,
775
795
  )
776
796
  error_message = await error_message_create.save()
777
797
  yield error_message
778
- await clear_thread_memory(input.agent_id, input.chat_id)
798
+ await clear_thread_memory(user_message.agent_id, user_message.chat_id)
779
799
  return
780
800
 
781
801
 
@@ -889,10 +909,7 @@ async def clean_agent_memory(
889
909
  async def thread_stats(agent_id: str, chat_id: str) -> list[BaseMessage]:
890
910
  thread_id = f"{agent_id}-{chat_id}"
891
911
  stream_config = {"configurable": {"thread_id": thread_id}}
892
- is_private = False
893
- if chat_id.startswith("owner") or chat_id.startswith("autonomous"):
894
- is_private = True
895
- executor, _ = await agent_executor(agent_id, is_private)
912
+ executor, _ = await agent_executor(agent_id)
896
913
  snap = await executor.aget_state(stream_config)
897
914
  if snap.values and "messages" in snap.values:
898
915
  return snap.values["messages"]