webagents 0.1.12__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.
Files changed (96) hide show
  1. webagents/__init__.py +18 -0
  2. webagents/agents/__init__.py +13 -0
  3. webagents/agents/core/__init__.py +19 -0
  4. webagents/agents/core/base_agent.py +1834 -0
  5. webagents/agents/core/handoffs.py +293 -0
  6. webagents/agents/handoffs/__init__.py +0 -0
  7. webagents/agents/interfaces/__init__.py +0 -0
  8. webagents/agents/lifecycle/__init__.py +0 -0
  9. webagents/agents/skills/__init__.py +109 -0
  10. webagents/agents/skills/base.py +136 -0
  11. webagents/agents/skills/core/__init__.py +8 -0
  12. webagents/agents/skills/core/guardrails/__init__.py +0 -0
  13. webagents/agents/skills/core/llm/__init__.py +0 -0
  14. webagents/agents/skills/core/llm/anthropic/__init__.py +1 -0
  15. webagents/agents/skills/core/llm/litellm/__init__.py +10 -0
  16. webagents/agents/skills/core/llm/litellm/skill.py +538 -0
  17. webagents/agents/skills/core/llm/openai/__init__.py +1 -0
  18. webagents/agents/skills/core/llm/xai/__init__.py +1 -0
  19. webagents/agents/skills/core/mcp/README.md +375 -0
  20. webagents/agents/skills/core/mcp/__init__.py +15 -0
  21. webagents/agents/skills/core/mcp/skill.py +731 -0
  22. webagents/agents/skills/core/memory/__init__.py +11 -0
  23. webagents/agents/skills/core/memory/long_term_memory/__init__.py +10 -0
  24. webagents/agents/skills/core/memory/long_term_memory/memory_skill.py +639 -0
  25. webagents/agents/skills/core/memory/short_term_memory/__init__.py +9 -0
  26. webagents/agents/skills/core/memory/short_term_memory/skill.py +341 -0
  27. webagents/agents/skills/core/memory/vector_memory/skill.py +447 -0
  28. webagents/agents/skills/core/planning/__init__.py +9 -0
  29. webagents/agents/skills/core/planning/planner.py +343 -0
  30. webagents/agents/skills/ecosystem/__init__.py +0 -0
  31. webagents/agents/skills/ecosystem/crewai/__init__.py +1 -0
  32. webagents/agents/skills/ecosystem/database/__init__.py +1 -0
  33. webagents/agents/skills/ecosystem/filesystem/__init__.py +0 -0
  34. webagents/agents/skills/ecosystem/google/__init__.py +0 -0
  35. webagents/agents/skills/ecosystem/google/calendar/__init__.py +6 -0
  36. webagents/agents/skills/ecosystem/google/calendar/skill.py +306 -0
  37. webagents/agents/skills/ecosystem/n8n/__init__.py +0 -0
  38. webagents/agents/skills/ecosystem/openai_agents/__init__.py +0 -0
  39. webagents/agents/skills/ecosystem/web/__init__.py +0 -0
  40. webagents/agents/skills/ecosystem/zapier/__init__.py +0 -0
  41. webagents/agents/skills/robutler/__init__.py +11 -0
  42. webagents/agents/skills/robutler/auth/README.md +63 -0
  43. webagents/agents/skills/robutler/auth/__init__.py +17 -0
  44. webagents/agents/skills/robutler/auth/skill.py +354 -0
  45. webagents/agents/skills/robutler/crm/__init__.py +18 -0
  46. webagents/agents/skills/robutler/crm/skill.py +368 -0
  47. webagents/agents/skills/robutler/discovery/README.md +281 -0
  48. webagents/agents/skills/robutler/discovery/__init__.py +16 -0
  49. webagents/agents/skills/robutler/discovery/skill.py +230 -0
  50. webagents/agents/skills/robutler/kv/__init__.py +6 -0
  51. webagents/agents/skills/robutler/kv/skill.py +80 -0
  52. webagents/agents/skills/robutler/message_history/__init__.py +9 -0
  53. webagents/agents/skills/robutler/message_history/skill.py +270 -0
  54. webagents/agents/skills/robutler/messages/__init__.py +0 -0
  55. webagents/agents/skills/robutler/nli/__init__.py +13 -0
  56. webagents/agents/skills/robutler/nli/skill.py +687 -0
  57. webagents/agents/skills/robutler/notifications/__init__.py +5 -0
  58. webagents/agents/skills/robutler/notifications/skill.py +141 -0
  59. webagents/agents/skills/robutler/payments/__init__.py +41 -0
  60. webagents/agents/skills/robutler/payments/exceptions.py +255 -0
  61. webagents/agents/skills/robutler/payments/skill.py +610 -0
  62. webagents/agents/skills/robutler/storage/__init__.py +10 -0
  63. webagents/agents/skills/robutler/storage/files/__init__.py +9 -0
  64. webagents/agents/skills/robutler/storage/files/skill.py +445 -0
  65. webagents/agents/skills/robutler/storage/json/__init__.py +9 -0
  66. webagents/agents/skills/robutler/storage/json/skill.py +336 -0
  67. webagents/agents/skills/robutler/storage/kv/skill.py +88 -0
  68. webagents/agents/skills/robutler/storage.py +389 -0
  69. webagents/agents/tools/__init__.py +0 -0
  70. webagents/agents/tools/decorators.py +426 -0
  71. webagents/agents/tracing/__init__.py +0 -0
  72. webagents/agents/workflows/__init__.py +0 -0
  73. webagents/api/__init__.py +17 -0
  74. webagents/api/client.py +1207 -0
  75. webagents/api/types.py +253 -0
  76. webagents/scripts/__init__.py +0 -0
  77. webagents/server/__init__.py +28 -0
  78. webagents/server/context/__init__.py +0 -0
  79. webagents/server/context/context_vars.py +121 -0
  80. webagents/server/core/__init__.py +0 -0
  81. webagents/server/core/app.py +843 -0
  82. webagents/server/core/middleware.py +69 -0
  83. webagents/server/core/models.py +98 -0
  84. webagents/server/core/monitoring.py +59 -0
  85. webagents/server/endpoints/__init__.py +0 -0
  86. webagents/server/interfaces/__init__.py +0 -0
  87. webagents/server/middleware.py +330 -0
  88. webagents/server/models.py +92 -0
  89. webagents/server/monitoring.py +659 -0
  90. webagents/utils/__init__.py +0 -0
  91. webagents/utils/logging.py +359 -0
  92. webagents-0.1.12.dist-info/METADATA +99 -0
  93. webagents-0.1.12.dist-info/RECORD +96 -0
  94. webagents-0.1.12.dist-info/WHEEL +4 -0
  95. webagents-0.1.12.dist-info/entry_points.txt +2 -0
  96. webagents-0.1.12.dist-info/licenses/LICENSE +1 -0
@@ -0,0 +1,447 @@
1
+ """
2
+ VectorMemorySkill - Milvus-backed vector memory for agent instructions/context
3
+
4
+ Features:
5
+ - Store and retrieve instruction documents (common or agent-specific)
6
+ - Tool to fetch relevant instructions for a problem (common + agent-specific)
7
+ - Owner-only tools to upload/remove documents
8
+
9
+ Env configuration:
10
+ - MILVUS_HOST (e.g., https://in03)
11
+ - MILVUS_PORT (e.g., 443)
12
+ - MILVUS_TOKEN (if required by Milvus/Cosmos)
13
+ - MILVUS_COLLECTION (default: robutler_memory)
14
+ - MILVUS_FORCE_RECREATE (truthy to recreate collection on init)
15
+ - EMBEDDING_MODEL (default: text-embedding-3-small)
16
+ - LITELLM_BASE_URL (default: http://localhost:2225)
17
+ - LITELLM_API_KEY or ROBUTLER_API_KEY (bearer for embeddings)
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ import os
23
+ import uuid
24
+ from typing import Any, Dict, List, Optional, Tuple
25
+
26
+ from webagents.agents.skills.base import Skill
27
+ from webagents.agents.tools.decorators import tool, prompt
28
+ from webagents.utils.logging import get_logger, log_skill_event, log_tool_execution
29
+
30
+ try:
31
+ from pymilvus import (
32
+ connections,
33
+ FieldSchema, CollectionSchema, DataType, Collection,
34
+ utility as milvus_utility,
35
+ )
36
+ _MILVUS_AVAILABLE = True
37
+ except Exception:
38
+ _MILVUS_AVAILABLE = False
39
+
40
+
41
+ def _is_truthy(val: Optional[str]) -> bool:
42
+ return str(val).lower() in {"1", "true", "yes", "y", "on"}
43
+
44
+
45
+ def _get_env_str(name: str, default: Optional[str] = None) -> Optional[str]:
46
+ v = os.getenv(name, default)
47
+ return v if v and str(v).strip() != "" else default
48
+
49
+
50
+ class VectorMemorySkill(Skill):
51
+ def __init__(self, config: Dict[str, Any] | None = None):
52
+ super().__init__(config or {}, scope="all")
53
+ self.config = config or {}
54
+ self.logger = None
55
+ self.collection: Optional[Collection] = None
56
+ self.dim: int = int(os.getenv("EMBEDDING_DIM", "1536"))
57
+ # Milvus config
58
+ self.milvus_host = _get_env_str("MILVUS_HOST", "http://localhost")
59
+ self.milvus_port = int(os.getenv("MILVUS_PORT", "19530"))
60
+ self.milvus_token = _get_env_str("MILVUS_TOKEN")
61
+ self.milvus_collection = _get_env_str("MILVUS_COLLECTION", "robutler_memory")
62
+ self.milvus_force_recreate = _is_truthy(os.getenv("MILVUS_FORCE_RECREATE", "false"))
63
+ # Embeddings config
64
+ self.embed_model = _get_env_str("EMBEDDING_MODEL", "text-embedding-3-small")
65
+ self.litellm_base = _get_env_str("LITELLM_BASE_URL", "http://localhost:2225")
66
+ self.litellm_key = _get_env_str("LITELLM_API_KEY") or _get_env_str("ROBUTLER_API_KEY")
67
+
68
+ async def initialize(self, agent) -> None:
69
+ self.agent = agent
70
+ self.logger = get_logger('skill.robutler.vector_memory', agent.name)
71
+ if not _MILVUS_AVAILABLE:
72
+ self.logger.warning("pymilvus not available; VectorMemorySkill disabled")
73
+ return
74
+ try:
75
+ connections.connect(
76
+ alias="default",
77
+ uri=self.milvus_host if self.milvus_host.startswith("http") else None,
78
+ host=None if self.milvus_host.startswith("http") else self.milvus_host,
79
+ port=str(self.milvus_port),
80
+ token=self.milvus_token,
81
+ )
82
+ except Exception as e:
83
+ self.logger.warning(f"Failed to connect to Milvus: {e}")
84
+ return
85
+
86
+ try:
87
+ if self.milvus_force_recreate and milvus_utility.has_collection(self.milvus_collection):
88
+ milvus_utility.drop_collection(self.milvus_collection)
89
+
90
+ if not milvus_utility.has_collection(self.milvus_collection):
91
+ fields = [
92
+ FieldSchema(name="id", dtype=DataType.VARCHAR, is_primary=True, max_length=64),
93
+ FieldSchema(name="agent_id", dtype=DataType.VARCHAR, max_length=64),
94
+ FieldSchema(name="owner_user_id", dtype=DataType.VARCHAR, max_length=64),
95
+ FieldSchema(name="title", dtype=DataType.VARCHAR, max_length=256),
96
+ FieldSchema(name="content", dtype=DataType.VARCHAR, max_length=8192),
97
+ FieldSchema(name="vector", dtype=DataType.FLOAT_VECTOR, dim=self.dim),
98
+ ]
99
+ schema = CollectionSchema(fields=fields, description="Robutler Vector Memory")
100
+ self.collection = Collection(name=self.milvus_collection, schema=schema)
101
+ try:
102
+ self.collection.create_index(
103
+ field_name="vector",
104
+ index_params={
105
+ "index_type": "IVF_FLAT",
106
+ "metric_type": "IP",
107
+ "params": {"nlist": 1024},
108
+ },
109
+ )
110
+ except Exception:
111
+ pass
112
+ self.collection.load()
113
+ else:
114
+ self.collection = Collection(self.milvus_collection)
115
+ try:
116
+ self.collection.load()
117
+ except Exception:
118
+ pass
119
+ self.logger.info(f"VectorMemorySkill initialized; collection={self.milvus_collection}")
120
+ try:
121
+ log_skill_event(self.agent.name, 'vector_memory', 'initialized', {
122
+ 'milvus_host': (self.milvus_host or '')[:40],
123
+ 'milvus_port': self.milvus_port,
124
+ 'collection': self.milvus_collection,
125
+ 'force_recreate': self.milvus_force_recreate,
126
+ 'embed_model': self.embed_model,
127
+ })
128
+ except Exception:
129
+ pass
130
+ except Exception as e:
131
+ self.logger.warning(f"Milvus collection init failed: {e}")
132
+ self.collection = None
133
+
134
+ async def _embed(self, texts: List[str]) -> List[List[float]]:
135
+ if not texts:
136
+ return []
137
+ try:
138
+ import httpx
139
+ headers = {"Content-Type": "application/json"}
140
+ if self.litellm_key:
141
+ headers["Authorization"] = f"Bearer {self.litellm_key}"
142
+ url = f"{self.litellm_base.rstrip('/')}/v1/embeddings"
143
+ payload = {"model": self.embed_model, "input": texts}
144
+ async with httpx.AsyncClient(timeout=20.0) as client:
145
+ resp = await client.post(url, json=payload, headers=headers)
146
+ resp.raise_for_status()
147
+ data = resp.json().get("data", [])
148
+ return [item.get("embedding", []) for item in data]
149
+ except Exception as e:
150
+ if self.logger:
151
+ self.logger.warning(f"Embedding failed: {e}")
152
+ return [[0.0] * self.dim for _ in texts]
153
+
154
+ def _ensure_collection(self) -> bool:
155
+ return bool(_MILVUS_AVAILABLE and self.collection)
156
+
157
+ @tool(description="Retrieve relevant instruction documents (common + agent-specific) for the current problem.")
158
+ async def fetch_instructions_tool(self, problem: str, top_k: int = 3, context: Any = None) -> str:
159
+ if not self._ensure_collection():
160
+ return "❌ Vector memory unavailable"
161
+ try:
162
+ agent_id = getattr(self.agent, 'id', None)
163
+ vectors = await self._embed([problem])
164
+ if not vectors:
165
+ return ""
166
+ qvec = vectors[0]
167
+ expr = "agent_id == ''"
168
+ if agent_id:
169
+ expr = f"({expr}) or agent_id == '{agent_id}'"
170
+ res = self.collection.search(
171
+ data=[qvec],
172
+ anns_field="vector",
173
+ param={"nprobe": 16},
174
+ limit=max(1, int(top_k)),
175
+ output_fields=["id", "title", "content", "agent_id"],
176
+ expr=expr,
177
+ )
178
+ hits = res[0] if res else []
179
+ docs: List[Tuple[str, str]] = []
180
+ for hit in hits:
181
+ row = hit.entity
182
+ title = row.get("title") or "Instruction"
183
+ content = row.get("content") or ""
184
+ if content:
185
+ docs.append((title, content))
186
+ if not docs:
187
+ try:
188
+ log_tool_execution(self.agent.name, 'vector_memory.fetch_instructions_tool', 0, success=True)
189
+ except Exception:
190
+ pass
191
+ return ""
192
+ combined = [f"# {t}\n{c}" for t, c in docs]
193
+ try:
194
+ log_tool_execution(self.agent.name, 'vector_memory.fetch_instructions_tool', 0, success=True)
195
+ except Exception:
196
+ pass
197
+ return "\n\n".join(combined)
198
+ except Exception as e:
199
+ if self.logger:
200
+ self.logger.error(f"fetch_instructions_tool error: {e}")
201
+ try:
202
+ log_tool_execution(self.agent.name, 'vector_memory.fetch_instructions_tool', 0, success=False)
203
+ except Exception:
204
+ pass
205
+ return ""
206
+
207
+ # @tool(description="Owner-only: upload an instruction document to the knowledge base (common or agent-specific).", scope="owner")
208
+ async def upload_instruction(self, title: str, content: str, agent_specific: bool = True, context: Any = None) -> str:
209
+ if not self._ensure_collection():
210
+ return "❌ Vector memory unavailable"
211
+ try:
212
+ agent_id = getattr(self.agent, 'id', None) if agent_specific else ""
213
+ owner_user_id = getattr(self.agent, 'owner_user_id', None) or ""
214
+ vecs = await self._embed([f"{title}\n\n{content}"])
215
+ vec = vecs[0] if vecs else [0.0] * self.dim
216
+ doc_id = uuid.uuid4().hex
217
+ entities = [
218
+ [doc_id],
219
+ [agent_id or ""],
220
+ [owner_user_id],
221
+ [title[:255]],
222
+ [content[:8000]],
223
+ [vec],
224
+ ]
225
+ self.collection.insert(entities)
226
+ try:
227
+ self.collection.flush()
228
+ except Exception:
229
+ pass
230
+ try:
231
+ log_tool_execution(self.agent.name, 'vector_memory.upload_instruction', 0, success=True)
232
+ except Exception:
233
+ pass
234
+ return f"✅ Uploaded instruction (id={doc_id})"
235
+ except Exception as e:
236
+ if self.logger:
237
+ self.logger.error(f"upload_instruction error: {e}")
238
+ try:
239
+ log_tool_execution(self.agent.name, 'vector_memory.upload_instruction', 0, success=False)
240
+ except Exception:
241
+ pass
242
+ return f"❌ Upload failed: {e}"
243
+
244
+ # @tool(description="Owner-only: remove an instruction document by id.", scope="owner")
245
+ async def remove_instruction(self, doc_id: str, context: Any = None) -> str:
246
+ if not self._ensure_collection():
247
+ return "❌ Vector memory unavailable"
248
+ try:
249
+ expr = f"id == '{doc_id}'"
250
+ self.collection.delete(expr)
251
+ try:
252
+ self.collection.flush()
253
+ except Exception:
254
+ pass
255
+ try:
256
+ log_tool_execution(self.agent.name, 'vector_memory.remove_instruction', 0, success=True)
257
+ except Exception:
258
+ pass
259
+ return f"🗑️ Removed instruction (id={doc_id})"
260
+ except Exception as e:
261
+ if self.logger:
262
+ self.logger.error(f"remove_instruction error: {e}")
263
+ try:
264
+ log_tool_execution(self.agent.name, 'vector_memory.remove_instruction', 0, success=False)
265
+ except Exception:
266
+ pass
267
+ return f"❌ Remove failed: {e}"
268
+
269
+ # ---------------- Admin tools for common instructions ----------------
270
+ # @tool(description="Admin: list common instruction documents (agent_id == '')", scope="admin")
271
+ async def list_common_instructions(self, limit: int = 50, context: Any = None) -> str:
272
+ if not self._ensure_collection():
273
+ return "❌ Vector memory unavailable"
274
+ try:
275
+ # Query all common docs (agent_id == '')
276
+ # Use a vector-less query via query API
277
+ results = self.collection.query(
278
+ expr="agent_id == ''",
279
+ output_fields=["id", "title", "owner_user_id"],
280
+ limit=max(1, int(limit))
281
+ )
282
+ if not results:
283
+ try:
284
+ log_tool_execution(self.agent.name, 'vector_memory.list_common_instructions', 0, success=True)
285
+ except Exception:
286
+ pass
287
+ return "(no common instructions)"
288
+ lines = [f"- {r.get('id')}: {r.get('title') or 'Untitled'} (owner={r.get('owner_user_id') or ''})" for r in results]
289
+ try:
290
+ log_tool_execution(self.agent.name, 'vector_memory.list_common_instructions', 0, success=True)
291
+ except Exception:
292
+ pass
293
+ return "\n".join(lines)
294
+ except Exception as e:
295
+ if self.logger:
296
+ self.logger.error(f"list_common_instructions error: {e}")
297
+ try:
298
+ log_tool_execution(self.agent.name, 'vector_memory.list_common_instructions', 0, success=False)
299
+ except Exception:
300
+ pass
301
+ return "❌ List failed"
302
+
303
+ # @tool(description="Admin: create a common instruction document", scope="admin")
304
+ async def create_common_instruction(self, title: str, content: str, context: Any = None) -> str:
305
+ if not self._ensure_collection():
306
+ return "❌ Vector memory unavailable"
307
+ try:
308
+ vecs = await self._embed([f"{title}\n\n{content}"])
309
+ vec = vecs[0] if vecs else [0.0] * self.dim
310
+ doc_id = uuid.uuid4().hex
311
+ entities = [
312
+ [doc_id],
313
+ [""], # agent_id empty => common
314
+ [getattr(self.agent, 'owner_user_id', '') or ''],
315
+ [title[:255]],
316
+ [content[:8000]],
317
+ [vec],
318
+ ]
319
+ self.collection.insert(entities)
320
+ try:
321
+ self.collection.flush()
322
+ except Exception:
323
+ pass
324
+ try:
325
+ log_tool_execution(self.agent.name, 'vector_memory.create_common_instruction', 0, success=True)
326
+ except Exception:
327
+ pass
328
+ return f"✅ Created common instruction (id={doc_id})"
329
+ except Exception as e:
330
+ if self.logger:
331
+ self.logger.error(f"create_common_instruction error: {e}")
332
+ try:
333
+ log_tool_execution(self.agent.name, 'vector_memory.create_common_instruction', 0, success=False)
334
+ except Exception:
335
+ pass
336
+ return f"❌ Create failed: {e}"
337
+
338
+ # @tool(description="Admin: update a common instruction document (title and/or content)", scope="admin")
339
+ async def update_common_instruction(self, doc_id: str, title: Optional[str] = None, content: Optional[str] = None, context: Any = None) -> str:
340
+ if not self._ensure_collection():
341
+ return "❌ Vector memory unavailable"
342
+ if not title and not content:
343
+ return "Nothing to update"
344
+ try:
345
+ # Fetch existing doc to preserve fields
346
+ rows = self.collection.query(expr=f"id == '{doc_id}' and agent_id == ''", output_fields=["id", "title", "content"], limit=1)
347
+ if not rows:
348
+ return "❌ Document not found or not common"
349
+ current = rows[0]
350
+ new_title = title if title is not None else current.get('title')
351
+ new_content = content if content is not None else current.get('content')
352
+ vecs = await self._embed([f"{new_title}\n\n{new_content}"])
353
+ vec = vecs[0] if vecs else [0.0] * self.dim
354
+ # Delete + insert (Milvus doesn't support partial update of vectors)
355
+ self.collection.delete(f"id == '{doc_id}'")
356
+ try:
357
+ self.collection.flush()
358
+ except Exception:
359
+ pass
360
+ entities = [
361
+ [doc_id],
362
+ [""],
363
+ [getattr(self.agent, 'owner_user_id', '') or ''],
364
+ [new_title[:255]],
365
+ [new_content[:8000]],
366
+ [vec],
367
+ ]
368
+ self.collection.insert(entities)
369
+ try:
370
+ self.collection.flush()
371
+ except Exception:
372
+ pass
373
+ try:
374
+ log_tool_execution(self.agent.name, 'vector_memory.update_common_instruction', 0, success=True)
375
+ except Exception:
376
+ pass
377
+ return "✅ Updated"
378
+ except Exception as e:
379
+ if self.logger:
380
+ self.logger.error(f"update_common_instruction error: {e}")
381
+ try:
382
+ log_tool_execution(self.agent.name, 'vector_memory.update_common_instruction', 0, success=False)
383
+ except Exception:
384
+ pass
385
+ return f"❌ Update failed: {e}"
386
+
387
+ # @tool(description="Admin: delete a common instruction document by id", scope="admin")
388
+ async def delete_common_instruction(self, doc_id: str, context: Any = None) -> str:
389
+ if not self._ensure_collection():
390
+ return "❌ Vector memory unavailable"
391
+ try:
392
+ self.collection.delete(f"id == '{doc_id}' and agent_id == ''")
393
+ try:
394
+ self.collection.flush()
395
+ except Exception:
396
+ pass
397
+ try:
398
+ log_tool_execution(self.agent.name, 'vector_memory.delete_common_instruction', 0, success=True)
399
+ except Exception:
400
+ pass
401
+ return "🗑️ Deleted"
402
+ except Exception as e:
403
+ if self.logger:
404
+ self.logger.error(f"delete_common_instruction error: {e}")
405
+ try:
406
+ log_tool_execution(self.agent.name, 'vector_memory.delete_common_instruction', 0, success=False)
407
+ except Exception:
408
+ pass
409
+ return f"❌ Delete failed: {e}"
410
+
411
+ def get_guidance_prompt(self) -> str:
412
+ return (
413
+ "You have access to a vector memory of instructions (common and agent-specific).\n"
414
+ "- You MAY call fetch_instructions_tool ONCE per conversation for domain-specific guidance.\n"
415
+ "- If the returned instructions are relevant, incorporate them into your reasoning.\n"
416
+ "- If the returned instructions are irrelevant or generic, ignore them and proceed without them.\n"
417
+ "- If you are the agent owner or an admin and need to curate knowledge, use the tools\n"
418
+ " upload_instruction / remove_instruction (owner) or create/update/delete_common_instruction (admin).\n"
419
+ )
420
+
421
+ def get_tool_prompt(self) -> str:
422
+ """Detailed prompt block that can be injected into the system prompt."""
423
+ return (
424
+ "- fetch_instructions_tool(problem, top_k=1): retrieve relevant instruction documents from memory\n"
425
+ "Use fetch_instructions_tool ONLY ONCE per conversation and only if you need specific domain guidance.\n"
426
+ )
427
+
428
+ # @prompt blocks to auto-inject scoped guidance
429
+ @prompt(priority=20, scope="all")
430
+ def vector_memory_general_prompt(self, context: Any = None) -> str:
431
+ return self.get_guidance_prompt() + "\n\n" + self.get_tool_prompt()
432
+
433
+ @prompt(priority=25, scope="owner")
434
+ def vector_memory_owner_prompt(self, context: Any = None) -> str:
435
+ return (
436
+ "OWNER: You may curate agent-specific instructions using upload_instruction(title, content, agent_specific=True)\n"
437
+ "and remove_instruction(doc_id). Use these to improve the agent's guidance over time.\n"
438
+ )
439
+
440
+ @prompt(priority=25, scope="admin")
441
+ def vector_memory_admin_prompt(self, context: Any = None) -> str:
442
+ return (
443
+ "ADMIN: You can manage common instructions using list/create/update/delete_common_instruction tools.\n"
444
+ "Use these to maintain global guidance shared across agents.\n"
445
+ )
446
+
447
+
@@ -0,0 +1,9 @@
1
+ """
2
+ Core Planning Skills - Robutler V2.0
3
+
4
+ Advanced task planning and orchestration capabilities.
5
+ """
6
+
7
+ from .planner import PlannerSkill, PlannerTask, PlannerState
8
+
9
+ __all__ = ['PlannerSkill', 'PlannerTask', 'PlannerState']