crewlayer 0.1.0__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.
- crewlayer/__init__.py +54 -0
- crewlayer/_actions.py +153 -0
- crewlayer/_client.py +87 -0
- crewlayer/_context.py +107 -0
- crewlayer/_exceptions.py +71 -0
- crewlayer/_http.py +101 -0
- crewlayer/_memory.py +192 -0
- crewlayer/_types.py +242 -0
- crewlayer/integrations/__init__.py +6 -0
- crewlayer/integrations/autogen.py +538 -0
- crewlayer/integrations/crewai.py +215 -0
- crewlayer/integrations/langchain.py +404 -0
- crewlayer/integrations/llamaindex.py +527 -0
- crewlayer/py.typed +0 -0
- crewlayer-0.1.0.dist-info/METADATA +232 -0
- crewlayer-0.1.0.dist-info/RECORD +17 -0
- crewlayer-0.1.0.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,538 @@
|
|
|
1
|
+
"""Microsoft AutoGen integration for the CrewLayer SDK.
|
|
2
|
+
|
|
3
|
+
Provides four adapters purpose-built for multi-agent workflows:
|
|
4
|
+
|
|
5
|
+
- ``CrewLayerConversableAgent`` — ConversableAgent that persists every
|
|
6
|
+
message to CrewLayer memory and logs
|
|
7
|
+
each send/receive as an action
|
|
8
|
+
- ``CrewLayerGroupChatManager`` — GroupChatManager that keeps the shared
|
|
9
|
+
CrewLayer blackboard in sync after every
|
|
10
|
+
group chat turn (the killer feature for
|
|
11
|
+
multi-agent workflows)
|
|
12
|
+
- ``CrewLayerAgentMemory`` — helper that loads an agent's long-term
|
|
13
|
+
memories as initial system context
|
|
14
|
+
- ``sync_agent_status`` — maps AutoGen thinking/idle states to
|
|
15
|
+
CrewLayer working/idle
|
|
16
|
+
|
|
17
|
+
Install::
|
|
18
|
+
|
|
19
|
+
pip install crewlayer[autogen]
|
|
20
|
+
|
|
21
|
+
Usage::
|
|
22
|
+
|
|
23
|
+
from crewlayer import CrewLayerClient
|
|
24
|
+
from crewlayer.integrations.autogen import (
|
|
25
|
+
CrewLayerConversableAgent,
|
|
26
|
+
CrewLayerGroupChatManager,
|
|
27
|
+
CrewLayerAgentMemory,
|
|
28
|
+
sync_agent_status,
|
|
29
|
+
)
|
|
30
|
+
import autogen
|
|
31
|
+
|
|
32
|
+
client = CrewLayerClient(api_key="crwl_...")
|
|
33
|
+
|
|
34
|
+
agent_a = CrewLayerConversableAgent(
|
|
35
|
+
name="researcher",
|
|
36
|
+
client=client,
|
|
37
|
+
agent_id="<uuid-a>",
|
|
38
|
+
system_message="You are a research assistant.",
|
|
39
|
+
llm_config={"model": "gpt-4"},
|
|
40
|
+
)
|
|
41
|
+
agent_b = CrewLayerConversableAgent(
|
|
42
|
+
name="writer",
|
|
43
|
+
client=client,
|
|
44
|
+
agent_id="<uuid-b>",
|
|
45
|
+
system_message="You are a technical writer.",
|
|
46
|
+
llm_config={"model": "gpt-4"},
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
groupchat = autogen.GroupChat(agents=[agent_a, agent_b], messages=[], max_round=10)
|
|
50
|
+
manager = CrewLayerGroupChatManager(
|
|
51
|
+
client=client,
|
|
52
|
+
group_id="project-alpha",
|
|
53
|
+
groupchat=groupchat,
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
# Load long-term memories as initial context
|
|
57
|
+
CrewLayerAgentMemory(client=client, agent_id="<uuid-a>").apply(agent_a)
|
|
58
|
+
|
|
59
|
+
# Every turn → blackboard updated automatically
|
|
60
|
+
agent_a.initiate_chat(manager, message="Let's start researching CrewLayer.")
|
|
61
|
+
"""
|
|
62
|
+
from __future__ import annotations
|
|
63
|
+
|
|
64
|
+
import time
|
|
65
|
+
from typing import Any
|
|
66
|
+
|
|
67
|
+
# ---------------------------------------------------------------------------
|
|
68
|
+
# Optional AutoGen imports — graceful fallback when not installed
|
|
69
|
+
# ---------------------------------------------------------------------------
|
|
70
|
+
|
|
71
|
+
try:
|
|
72
|
+
from autogen import ConversableAgent as _AGConversableAgent # type: ignore[import]
|
|
73
|
+
from autogen import GroupChatManager as _AGGroupChatManager # type: ignore[import]
|
|
74
|
+
_AUTOGEN = True
|
|
75
|
+
except ImportError:
|
|
76
|
+
_AUTOGEN = False
|
|
77
|
+
|
|
78
|
+
class _AutoGenStub: # type: ignore[no-redef]
|
|
79
|
+
"""Minimal stub for testing without AutoGen installed."""
|
|
80
|
+
|
|
81
|
+
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
|
82
|
+
self.name: str = str(kwargs.get("name", ""))
|
|
83
|
+
self.system_message: str = str(kwargs.get("system_message", ""))
|
|
84
|
+
|
|
85
|
+
def send(self, message: Any, recipient: Any, **kwargs: Any) -> None:
|
|
86
|
+
pass
|
|
87
|
+
|
|
88
|
+
def receive(self, message: Any, sender: Any, **kwargs: Any) -> None:
|
|
89
|
+
pass
|
|
90
|
+
|
|
91
|
+
def update_system_message(self, system_message: str) -> None:
|
|
92
|
+
self.system_message = system_message
|
|
93
|
+
|
|
94
|
+
_AGConversableAgent = _AutoGenStub # type: ignore[assignment, misc]
|
|
95
|
+
_AGGroupChatManager = _AutoGenStub # type: ignore[assignment, misc]
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
# ---------------------------------------------------------------------------
|
|
99
|
+
# Internal helpers
|
|
100
|
+
# ---------------------------------------------------------------------------
|
|
101
|
+
|
|
102
|
+
# AutoGen agent-status → CrewLayer status
|
|
103
|
+
_STATUS_MAP: dict[str, str] = {
|
|
104
|
+
"thinking": "working",
|
|
105
|
+
"replying": "working",
|
|
106
|
+
"generating": "working",
|
|
107
|
+
"processing": "working",
|
|
108
|
+
"waiting": "idle",
|
|
109
|
+
"idle": "idle",
|
|
110
|
+
"error": "error",
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def _extract_content(message: Any) -> str:
|
|
115
|
+
"""Return plain-text content from an AutoGen message (str or dict)."""
|
|
116
|
+
if message is None:
|
|
117
|
+
return ""
|
|
118
|
+
if isinstance(message, str):
|
|
119
|
+
return message
|
|
120
|
+
if isinstance(message, dict):
|
|
121
|
+
content = message.get("content")
|
|
122
|
+
if content is not None:
|
|
123
|
+
return str(content)
|
|
124
|
+
if "tool_calls" in message:
|
|
125
|
+
return str(message["tool_calls"])
|
|
126
|
+
return str(message)
|
|
127
|
+
return str(message)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def _agent_name(agent: Any) -> str:
|
|
131
|
+
return getattr(agent, "name", None) or str(agent)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
# ---------------------------------------------------------------------------
|
|
135
|
+
# CrewLayerConversableAgent
|
|
136
|
+
# ---------------------------------------------------------------------------
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
class CrewLayerConversableAgent(_AGConversableAgent): # type: ignore[misc]
|
|
140
|
+
"""AutoGen ``ConversableAgent`` with automatic CrewLayer persistence.
|
|
141
|
+
|
|
142
|
+
Every message sent or received is:
|
|
143
|
+
- appended to CrewLayer short-term memory (builds conversation history)
|
|
144
|
+
- logged as an immutable action entry (full audit trail with duration)
|
|
145
|
+
|
|
146
|
+
CrewLayer-specific parameters are keyword-only and separated from the
|
|
147
|
+
AutoGen parameters, so all existing AutoGen kwargs pass through unchanged.
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
name: Agent name (forwarded to AutoGen).
|
|
151
|
+
client: A ``CrewLayerClient`` (sync) instance.
|
|
152
|
+
agent_id: Target agent UUID in CrewLayer.
|
|
153
|
+
session_id: Session key for short-term memory (default ``"default"``).
|
|
154
|
+
**kwargs: All other kwargs forwarded to ``ConversableAgent.__init__``.
|
|
155
|
+
|
|
156
|
+
Example::
|
|
157
|
+
|
|
158
|
+
agent = CrewLayerConversableAgent(
|
|
159
|
+
name="assistant",
|
|
160
|
+
client=client,
|
|
161
|
+
agent_id="agent-uuid",
|
|
162
|
+
system_message="You are helpful.",
|
|
163
|
+
llm_config={"model": "gpt-4"},
|
|
164
|
+
)
|
|
165
|
+
"""
|
|
166
|
+
|
|
167
|
+
def __init__(
|
|
168
|
+
self,
|
|
169
|
+
name: str,
|
|
170
|
+
*,
|
|
171
|
+
client: Any,
|
|
172
|
+
agent_id: str,
|
|
173
|
+
session_id: str = "default",
|
|
174
|
+
**kwargs: Any,
|
|
175
|
+
) -> None:
|
|
176
|
+
super().__init__(name=name, **kwargs)
|
|
177
|
+
# __dict__ assignment bypasses Pydantic __setattr__ if AutoGen ever
|
|
178
|
+
# switches to Pydantic models.
|
|
179
|
+
self.__dict__.update({
|
|
180
|
+
"_cl_client": client,
|
|
181
|
+
"_cl_agent_id": agent_id,
|
|
182
|
+
"_cl_session": session_id,
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
# ------------------------------------------------------------------
|
|
186
|
+
# AutoGen ConversableAgent overrides
|
|
187
|
+
# ------------------------------------------------------------------
|
|
188
|
+
|
|
189
|
+
def send(
|
|
190
|
+
self,
|
|
191
|
+
message: Any,
|
|
192
|
+
recipient: Any,
|
|
193
|
+
request_reply: bool | None = None,
|
|
194
|
+
silent: bool | None = False,
|
|
195
|
+
) -> None:
|
|
196
|
+
"""Send a message; log the action and persist to memory afterwards."""
|
|
197
|
+
start = time.monotonic()
|
|
198
|
+
result = super().send(
|
|
199
|
+
message, recipient,
|
|
200
|
+
request_reply=request_reply,
|
|
201
|
+
silent=silent,
|
|
202
|
+
)
|
|
203
|
+
duration_ms = max(0, int((time.monotonic() - start) * 1000))
|
|
204
|
+
content = _extract_content(message)
|
|
205
|
+
recipient_name = _agent_name(recipient)
|
|
206
|
+
self._cl_save(
|
|
207
|
+
role="assistant",
|
|
208
|
+
content=content,
|
|
209
|
+
metadata={"direction": "send", "to": recipient_name},
|
|
210
|
+
)
|
|
211
|
+
self._cl_log(
|
|
212
|
+
tool_name="autogen.send",
|
|
213
|
+
input_params={"message": content[:500], "to": recipient_name},
|
|
214
|
+
output_result={},
|
|
215
|
+
duration_ms=duration_ms,
|
|
216
|
+
)
|
|
217
|
+
return result
|
|
218
|
+
|
|
219
|
+
def receive(
|
|
220
|
+
self,
|
|
221
|
+
message: Any,
|
|
222
|
+
sender: Any,
|
|
223
|
+
request_reply: bool | None = None,
|
|
224
|
+
silent: bool | None = False,
|
|
225
|
+
) -> None:
|
|
226
|
+
"""Receive a message; persist to memory first, then log the action."""
|
|
227
|
+
content = _extract_content(message)
|
|
228
|
+
sender_name = _agent_name(sender)
|
|
229
|
+
|
|
230
|
+
# Save the incoming message before processing so it's preserved even
|
|
231
|
+
# if processing later raises.
|
|
232
|
+
self._cl_save(
|
|
233
|
+
role="user",
|
|
234
|
+
content=content,
|
|
235
|
+
metadata={"direction": "receive", "from": sender_name},
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
start = time.monotonic()
|
|
239
|
+
result = super().receive(
|
|
240
|
+
message, sender,
|
|
241
|
+
request_reply=request_reply,
|
|
242
|
+
silent=silent,
|
|
243
|
+
)
|
|
244
|
+
duration_ms = max(0, int((time.monotonic() - start) * 1000))
|
|
245
|
+
|
|
246
|
+
self._cl_log(
|
|
247
|
+
tool_name="autogen.receive",
|
|
248
|
+
input_params={"message": content[:500], "from": sender_name},
|
|
249
|
+
output_result={},
|
|
250
|
+
duration_ms=duration_ms,
|
|
251
|
+
)
|
|
252
|
+
return result
|
|
253
|
+
|
|
254
|
+
# ------------------------------------------------------------------
|
|
255
|
+
# Internal helpers
|
|
256
|
+
# ------------------------------------------------------------------
|
|
257
|
+
|
|
258
|
+
def _cl_save(self, role: str, content: str, metadata: dict | None = None) -> None:
|
|
259
|
+
"""Append a message to CrewLayer short-term memory — never raises."""
|
|
260
|
+
try:
|
|
261
|
+
self._cl_client.memory.append(
|
|
262
|
+
self._cl_agent_id,
|
|
263
|
+
role,
|
|
264
|
+
content,
|
|
265
|
+
session_id=self._cl_session,
|
|
266
|
+
metadata=metadata or {},
|
|
267
|
+
)
|
|
268
|
+
except Exception:
|
|
269
|
+
pass
|
|
270
|
+
|
|
271
|
+
def _cl_log(
|
|
272
|
+
self,
|
|
273
|
+
tool_name: str,
|
|
274
|
+
input_params: dict,
|
|
275
|
+
output_result: dict,
|
|
276
|
+
duration_ms: int | None = None,
|
|
277
|
+
) -> None:
|
|
278
|
+
"""Log an action to CrewLayer — never raises."""
|
|
279
|
+
try:
|
|
280
|
+
self._cl_client.actions.log(
|
|
281
|
+
self._cl_agent_id,
|
|
282
|
+
tool_name=tool_name,
|
|
283
|
+
input_params=input_params,
|
|
284
|
+
output_result=output_result,
|
|
285
|
+
status="success",
|
|
286
|
+
session_id=self._cl_session,
|
|
287
|
+
duration_ms=duration_ms,
|
|
288
|
+
)
|
|
289
|
+
except Exception:
|
|
290
|
+
pass
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
# ---------------------------------------------------------------------------
|
|
294
|
+
# CrewLayerGroupChatManager
|
|
295
|
+
# ---------------------------------------------------------------------------
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
class CrewLayerGroupChatManager(_AGGroupChatManager): # type: ignore[misc]
|
|
299
|
+
"""AutoGen ``GroupChatManager`` that syncs every turn to the CrewLayer blackboard.
|
|
300
|
+
|
|
301
|
+
After each message in the group chat, two blackboard entries are written:
|
|
302
|
+
|
|
303
|
+
* ``latest_turn`` — the most recent speaker, content, and turn counter
|
|
304
|
+
* ``agent:{name}`` — each speaker's most recent message
|
|
305
|
+
|
|
306
|
+
This gives every agent (and external observers) a shared, persistent view
|
|
307
|
+
of the conversation state at ``context.read(group_id, "latest_turn")``.
|
|
308
|
+
|
|
309
|
+
Args:
|
|
310
|
+
client: A ``CrewLayerClient`` (sync) instance.
|
|
311
|
+
group_id: Blackboard namespace (default: ``"groupchat:{manager_name}"``).
|
|
312
|
+
groupchat: The ``autogen.GroupChat`` instance (forwarded to AutoGen).
|
|
313
|
+
name: Manager agent name (default ``"group_chat_manager"``).
|
|
314
|
+
**kwargs: All other kwargs forwarded to ``GroupChatManager.__init__``.
|
|
315
|
+
|
|
316
|
+
Example::
|
|
317
|
+
|
|
318
|
+
groupchat = autogen.GroupChat(agents=[a, b], messages=[], max_round=10)
|
|
319
|
+
manager = CrewLayerGroupChatManager(
|
|
320
|
+
client=client,
|
|
321
|
+
group_id="project-alpha",
|
|
322
|
+
groupchat=groupchat,
|
|
323
|
+
)
|
|
324
|
+
# After each turn: client.context.read("project-alpha", "latest_turn")
|
|
325
|
+
"""
|
|
326
|
+
|
|
327
|
+
def __init__(
|
|
328
|
+
self,
|
|
329
|
+
*,
|
|
330
|
+
client: Any,
|
|
331
|
+
group_id: str | None = None,
|
|
332
|
+
groupchat: Any = None,
|
|
333
|
+
name: str = "group_chat_manager",
|
|
334
|
+
**kwargs: Any,
|
|
335
|
+
) -> None:
|
|
336
|
+
if groupchat is not None:
|
|
337
|
+
super().__init__(groupchat=groupchat, name=name, **kwargs)
|
|
338
|
+
else:
|
|
339
|
+
super().__init__(name=name, **kwargs)
|
|
340
|
+
|
|
341
|
+
effective_group_id = group_id or f"groupchat:{name}"
|
|
342
|
+
self.__dict__.update({
|
|
343
|
+
"_cl_client": client,
|
|
344
|
+
"_cl_group_id": effective_group_id,
|
|
345
|
+
"_cl_turn": 0,
|
|
346
|
+
})
|
|
347
|
+
|
|
348
|
+
# ------------------------------------------------------------------
|
|
349
|
+
# AutoGen GroupChatManager override
|
|
350
|
+
# ------------------------------------------------------------------
|
|
351
|
+
|
|
352
|
+
def receive(
|
|
353
|
+
self,
|
|
354
|
+
message: Any,
|
|
355
|
+
sender: Any,
|
|
356
|
+
request_reply: bool | None = None,
|
|
357
|
+
silent: bool | None = False,
|
|
358
|
+
) -> None:
|
|
359
|
+
"""Process a group chat message and sync state to the blackboard."""
|
|
360
|
+
result = super().receive(
|
|
361
|
+
message, sender,
|
|
362
|
+
request_reply=request_reply,
|
|
363
|
+
silent=silent,
|
|
364
|
+
)
|
|
365
|
+
try:
|
|
366
|
+
self._cl_write_blackboard(message, sender)
|
|
367
|
+
except Exception:
|
|
368
|
+
pass # Never block group chat coordination
|
|
369
|
+
return result
|
|
370
|
+
|
|
371
|
+
# ------------------------------------------------------------------
|
|
372
|
+
# Blackboard helpers
|
|
373
|
+
# ------------------------------------------------------------------
|
|
374
|
+
|
|
375
|
+
def _cl_write_blackboard(self, message: Any, sender: Any) -> None:
|
|
376
|
+
"""Write sender's message to the shared blackboard namespace."""
|
|
377
|
+
self._cl_turn += 1
|
|
378
|
+
content = _extract_content(message)
|
|
379
|
+
sender_name = _agent_name(sender)
|
|
380
|
+
|
|
381
|
+
self._cl_client.context.write(
|
|
382
|
+
self._cl_group_id,
|
|
383
|
+
"latest_turn",
|
|
384
|
+
{
|
|
385
|
+
"agent": sender_name,
|
|
386
|
+
"content": content[:1000],
|
|
387
|
+
"turn": self._cl_turn,
|
|
388
|
+
},
|
|
389
|
+
written_by=sender_name,
|
|
390
|
+
)
|
|
391
|
+
self._cl_client.context.write(
|
|
392
|
+
self._cl_group_id,
|
|
393
|
+
f"agent:{sender_name}",
|
|
394
|
+
{
|
|
395
|
+
"last_message": content[:1000],
|
|
396
|
+
"turn": self._cl_turn,
|
|
397
|
+
},
|
|
398
|
+
written_by=sender_name,
|
|
399
|
+
)
|
|
400
|
+
|
|
401
|
+
def get_shared_context(self) -> Any:
|
|
402
|
+
"""Return all blackboard entries for this group's namespace.
|
|
403
|
+
|
|
404
|
+
Returns a ``ContextNamespace`` with a list of ``ContextEntry`` objects,
|
|
405
|
+
one per agent and the ``latest_turn`` entry.
|
|
406
|
+
|
|
407
|
+
Example::
|
|
408
|
+
|
|
409
|
+
ctx = manager.get_shared_context()
|
|
410
|
+
for entry in ctx.entries:
|
|
411
|
+
print(f"{entry.key}: {entry.value}")
|
|
412
|
+
"""
|
|
413
|
+
return self._cl_client.context.list_namespace(self._cl_group_id)
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
# ---------------------------------------------------------------------------
|
|
417
|
+
# CrewLayerAgentMemory
|
|
418
|
+
# ---------------------------------------------------------------------------
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
class CrewLayerAgentMemory:
|
|
422
|
+
"""Loads an agent's long-term memories as initial system context.
|
|
423
|
+
|
|
424
|
+
Call ``apply(agent)`` before starting a conversation to pre-load relevant
|
|
425
|
+
memories into the agent's system message. Useful for giving agents
|
|
426
|
+
continuity across sessions without manually managing context.
|
|
427
|
+
|
|
428
|
+
Args:
|
|
429
|
+
client: A ``CrewLayerClient`` (sync) instance.
|
|
430
|
+
agent_id: Target agent UUID.
|
|
431
|
+
query: Semantic query used to select relevant memories
|
|
432
|
+
(default: ``"agent background context and history"``).
|
|
433
|
+
limit: Maximum number of memories to load (default ``5``).
|
|
434
|
+
|
|
435
|
+
Example::
|
|
436
|
+
|
|
437
|
+
mem = CrewLayerAgentMemory(client=client, agent_id="agent-uuid")
|
|
438
|
+
mem.apply(agent) # enriches agent.system_message
|
|
439
|
+
agent.initiate_chat(other, message="Hello")
|
|
440
|
+
"""
|
|
441
|
+
|
|
442
|
+
def __init__(
|
|
443
|
+
self,
|
|
444
|
+
*,
|
|
445
|
+
client: Any,
|
|
446
|
+
agent_id: str,
|
|
447
|
+
query: str = "agent background context and history",
|
|
448
|
+
limit: int = 5,
|
|
449
|
+
) -> None:
|
|
450
|
+
self._client = client
|
|
451
|
+
self._agent_id = agent_id
|
|
452
|
+
self._query = query
|
|
453
|
+
self._limit = limit
|
|
454
|
+
|
|
455
|
+
def apply(self, agent: Any) -> None:
|
|
456
|
+
"""Prepend relevant long-term memories to *agent*'s system message.
|
|
457
|
+
|
|
458
|
+
If no memories are found the agent is left unchanged.
|
|
459
|
+
Respects AutoGen's ``update_system_message()`` API; falls back to
|
|
460
|
+
direct attribute assignment for custom or stub agents.
|
|
461
|
+
"""
|
|
462
|
+
results = self._client.memory.recall(
|
|
463
|
+
self._agent_id, self._query, limit=self._limit
|
|
464
|
+
)
|
|
465
|
+
if not results.results:
|
|
466
|
+
return
|
|
467
|
+
|
|
468
|
+
memory_lines = "\n".join(f"- {item.content}" for item in results.results)
|
|
469
|
+
memory_block = (
|
|
470
|
+
"Relevant memories from previous sessions:\n" + memory_lines
|
|
471
|
+
)
|
|
472
|
+
|
|
473
|
+
current = getattr(agent, "system_message", "") or ""
|
|
474
|
+
new_message = f"{memory_block}\n\n{current}" if current else memory_block
|
|
475
|
+
|
|
476
|
+
if callable(getattr(agent, "update_system_message", None)):
|
|
477
|
+
agent.update_system_message(new_message)
|
|
478
|
+
else:
|
|
479
|
+
try:
|
|
480
|
+
agent.system_message = new_message
|
|
481
|
+
except (AttributeError, TypeError):
|
|
482
|
+
pass
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
# ---------------------------------------------------------------------------
|
|
486
|
+
# sync_agent_status
|
|
487
|
+
# ---------------------------------------------------------------------------
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
def sync_agent_status(
|
|
491
|
+
client: Any,
|
|
492
|
+
agent_id: str,
|
|
493
|
+
autogen_status: str,
|
|
494
|
+
*,
|
|
495
|
+
session_id: str | None = None,
|
|
496
|
+
) -> None:
|
|
497
|
+
"""Synchronise an AutoGen agent state with CrewLayer's agent status.
|
|
498
|
+
|
|
499
|
+
AutoGen status strings are mapped to CrewLayer's status enum:
|
|
500
|
+
|
|
501
|
+
+--------------+------------------+
|
|
502
|
+
| AutoGen | CrewLayer |
|
|
503
|
+
+==============+==================+
|
|
504
|
+
| thinking | working |
|
|
505
|
+
| replying | working |
|
|
506
|
+
| generating | working |
|
|
507
|
+
| processing | working |
|
|
508
|
+
| waiting | idle |
|
|
509
|
+
| idle | idle |
|
|
510
|
+
| error | error |
|
|
511
|
+
+--------------+------------------+
|
|
512
|
+
|
|
513
|
+
Unknown strings default to ``idle``.
|
|
514
|
+
|
|
515
|
+
The call is best-effort — it silently swallows all exceptions so it never
|
|
516
|
+
blocks the agent's execution.
|
|
517
|
+
|
|
518
|
+
Args:
|
|
519
|
+
client: A ``CrewLayerClient`` (sync) instance.
|
|
520
|
+
agent_id: Target agent UUID.
|
|
521
|
+
autogen_status: AutoGen status string (case-insensitive).
|
|
522
|
+
session_id: Optional current session to associate with the status.
|
|
523
|
+
|
|
524
|
+
Example::
|
|
525
|
+
|
|
526
|
+
sync_agent_status(client, agent_id, "thinking")
|
|
527
|
+
response = agent.generate_reply(messages)
|
|
528
|
+
sync_agent_status(client, agent_id, "idle")
|
|
529
|
+
"""
|
|
530
|
+
crewlayer_status = _STATUS_MAP.get(autogen_status.lower(), "idle")
|
|
531
|
+
try:
|
|
532
|
+
client._http.request(
|
|
533
|
+
"PATCH",
|
|
534
|
+
f"/v1/agents/{agent_id}/status",
|
|
535
|
+
json={"status": crewlayer_status, "session_id": session_id},
|
|
536
|
+
)
|
|
537
|
+
except Exception:
|
|
538
|
+
pass
|