alma-memory 0.2.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.
- alma/__init__.py +75 -0
- alma/config/__init__.py +5 -0
- alma/config/loader.py +156 -0
- alma/core.py +322 -0
- alma/harness/__init__.py +35 -0
- alma/harness/base.py +377 -0
- alma/harness/domains.py +689 -0
- alma/integration/__init__.py +62 -0
- alma/integration/claude_agents.py +432 -0
- alma/integration/helena.py +413 -0
- alma/integration/victor.py +447 -0
- alma/learning/__init__.py +86 -0
- alma/learning/forgetting.py +1396 -0
- alma/learning/heuristic_extractor.py +374 -0
- alma/learning/protocols.py +326 -0
- alma/learning/validation.py +341 -0
- alma/mcp/__init__.py +45 -0
- alma/mcp/__main__.py +155 -0
- alma/mcp/resources.py +121 -0
- alma/mcp/server.py +533 -0
- alma/mcp/tools.py +374 -0
- alma/retrieval/__init__.py +53 -0
- alma/retrieval/cache.py +1062 -0
- alma/retrieval/embeddings.py +202 -0
- alma/retrieval/engine.py +287 -0
- alma/retrieval/scoring.py +334 -0
- alma/storage/__init__.py +20 -0
- alma/storage/azure_cosmos.py +972 -0
- alma/storage/base.py +372 -0
- alma/storage/file_based.py +583 -0
- alma/storage/sqlite_local.py +912 -0
- alma/types.py +216 -0
- alma_memory-0.2.0.dist-info/METADATA +327 -0
- alma_memory-0.2.0.dist-info/RECORD +36 -0
- alma_memory-0.2.0.dist-info/WHEEL +5 -0
- alma_memory-0.2.0.dist-info/top_level.txt +1 -0
alma/harness/domains.py
ADDED
|
@@ -0,0 +1,689 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ALMA Domain-Specific Harness Configurations.
|
|
3
|
+
|
|
4
|
+
Pre-built configurations for common domains:
|
|
5
|
+
- Coding: Testing, API development, code review
|
|
6
|
+
- Research: Market analysis, competitive intelligence, data synthesis
|
|
7
|
+
- Content: Marketing copy, documentation, creative writing
|
|
8
|
+
- Operations: Customer support, automation, process management
|
|
9
|
+
|
|
10
|
+
Each domain includes:
|
|
11
|
+
- Default tools and settings
|
|
12
|
+
- Memory schema with appropriate scopes
|
|
13
|
+
- Agent templates
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from dataclasses import dataclass, field
|
|
17
|
+
from typing import List, Dict, Any, Optional
|
|
18
|
+
|
|
19
|
+
from alma.harness.base import (
|
|
20
|
+
Setting,
|
|
21
|
+
Tool,
|
|
22
|
+
ToolType,
|
|
23
|
+
Agent,
|
|
24
|
+
MemorySchema,
|
|
25
|
+
Harness,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# =============================================================================
|
|
30
|
+
# CODING DOMAIN
|
|
31
|
+
# =============================================================================
|
|
32
|
+
|
|
33
|
+
class CodingDomain:
|
|
34
|
+
"""Pre-built configurations for coding/development agents."""
|
|
35
|
+
|
|
36
|
+
@staticmethod
|
|
37
|
+
def testing_schema() -> MemorySchema:
|
|
38
|
+
"""Memory schema for testing agents (Helena-style)."""
|
|
39
|
+
return MemorySchema(
|
|
40
|
+
domain="testing",
|
|
41
|
+
description="Frontend and backend testing patterns, strategies, and outcomes",
|
|
42
|
+
learnable_categories=[
|
|
43
|
+
"testing_strategies",
|
|
44
|
+
"selector_patterns",
|
|
45
|
+
"ui_component_patterns",
|
|
46
|
+
"form_testing",
|
|
47
|
+
"accessibility_testing",
|
|
48
|
+
"api_testing",
|
|
49
|
+
"database_validation",
|
|
50
|
+
"error_handling_patterns",
|
|
51
|
+
],
|
|
52
|
+
forbidden_categories=[
|
|
53
|
+
"deployment_procedures",
|
|
54
|
+
"infrastructure_config",
|
|
55
|
+
"security_credentials",
|
|
56
|
+
],
|
|
57
|
+
heuristic_templates=[
|
|
58
|
+
"When testing {component_type}, {strategy} works {confidence}% of the time",
|
|
59
|
+
"For {error_type} errors, check {diagnostic_steps} first",
|
|
60
|
+
"Selector pattern {pattern} is reliable for {use_case}",
|
|
61
|
+
],
|
|
62
|
+
outcome_fields=[
|
|
63
|
+
"test_type",
|
|
64
|
+
"component_tested",
|
|
65
|
+
"pass_rate",
|
|
66
|
+
"flakiness_score",
|
|
67
|
+
"execution_time_ms",
|
|
68
|
+
],
|
|
69
|
+
min_occurrences=3,
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
@staticmethod
|
|
73
|
+
def api_dev_schema() -> MemorySchema:
|
|
74
|
+
"""Memory schema for API development agents (Victor-style)."""
|
|
75
|
+
return MemorySchema(
|
|
76
|
+
domain="api_development",
|
|
77
|
+
description="API design, implementation patterns, and validation strategies",
|
|
78
|
+
learnable_categories=[
|
|
79
|
+
"api_design_patterns",
|
|
80
|
+
"authentication_patterns",
|
|
81
|
+
"error_handling",
|
|
82
|
+
"performance_optimization",
|
|
83
|
+
"database_query_patterns",
|
|
84
|
+
"caching_strategies",
|
|
85
|
+
],
|
|
86
|
+
forbidden_categories=[
|
|
87
|
+
"frontend_styling",
|
|
88
|
+
"ui_testing",
|
|
89
|
+
"marketing_content",
|
|
90
|
+
],
|
|
91
|
+
heuristic_templates=[
|
|
92
|
+
"For {endpoint_type} endpoints, use {pattern} for better {metric}",
|
|
93
|
+
"When handling {error_type}, return {response_pattern}",
|
|
94
|
+
"Database queries for {use_case} perform best with {optimization}",
|
|
95
|
+
],
|
|
96
|
+
outcome_fields=[
|
|
97
|
+
"endpoint",
|
|
98
|
+
"method",
|
|
99
|
+
"response_time_ms",
|
|
100
|
+
"error_rate",
|
|
101
|
+
"validation_passed",
|
|
102
|
+
],
|
|
103
|
+
min_occurrences=3,
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
@staticmethod
|
|
107
|
+
def testing_setting() -> Setting:
|
|
108
|
+
"""Default setting for testing agents."""
|
|
109
|
+
return Setting(
|
|
110
|
+
name="Testing Environment",
|
|
111
|
+
description="Environment for automated testing with browser and API tools",
|
|
112
|
+
tools=[
|
|
113
|
+
Tool(
|
|
114
|
+
name="playwright",
|
|
115
|
+
description="Browser automation for UI testing",
|
|
116
|
+
tool_type=ToolType.EXECUTION,
|
|
117
|
+
constraints=["Use explicit waits, not sleep()", "Prefer role-based selectors"],
|
|
118
|
+
),
|
|
119
|
+
Tool(
|
|
120
|
+
name="api_client",
|
|
121
|
+
description="HTTP client for API testing",
|
|
122
|
+
tool_type=ToolType.DATA_ACCESS,
|
|
123
|
+
constraints=["Log all requests/responses", "Handle timeouts gracefully"],
|
|
124
|
+
),
|
|
125
|
+
Tool(
|
|
126
|
+
name="database_query",
|
|
127
|
+
description="Direct database access for validation",
|
|
128
|
+
tool_type=ToolType.DATA_ACCESS,
|
|
129
|
+
constraints=["Read-only queries", "No production writes"],
|
|
130
|
+
),
|
|
131
|
+
],
|
|
132
|
+
global_constraints=[
|
|
133
|
+
"Never commit test credentials",
|
|
134
|
+
"Clean up test data after runs",
|
|
135
|
+
"Log all test outcomes for learning",
|
|
136
|
+
],
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
@staticmethod
|
|
140
|
+
def create_helena(alma: Any) -> Harness:
|
|
141
|
+
"""Create a Helena-style frontend testing agent."""
|
|
142
|
+
setting = CodingDomain.testing_setting()
|
|
143
|
+
schema = CodingDomain.testing_schema()
|
|
144
|
+
|
|
145
|
+
agent = Agent(
|
|
146
|
+
name="helena",
|
|
147
|
+
role="Frontend QA Specialist",
|
|
148
|
+
description=(
|
|
149
|
+
"Expert in frontend testing, Playwright automation, accessibility "
|
|
150
|
+
"validation, and UI consistency. Methodical, thorough, documents everything."
|
|
151
|
+
),
|
|
152
|
+
memory_schema=schema,
|
|
153
|
+
traits=[
|
|
154
|
+
"Methodical and systematic",
|
|
155
|
+
"Documents edge cases thoroughly",
|
|
156
|
+
"Prioritizes user experience",
|
|
157
|
+
"Catches visual regressions",
|
|
158
|
+
],
|
|
159
|
+
default_actions=[
|
|
160
|
+
"Test happy path first",
|
|
161
|
+
"Check accessibility for all interactive elements",
|
|
162
|
+
"Validate responsive behavior",
|
|
163
|
+
"Document all findings with screenshots",
|
|
164
|
+
],
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
return Harness(setting=setting, agent=agent, alma=alma)
|
|
168
|
+
|
|
169
|
+
@staticmethod
|
|
170
|
+
def create_victor(alma: Any) -> Harness:
|
|
171
|
+
"""Create a Victor-style backend testing agent."""
|
|
172
|
+
setting = CodingDomain.testing_setting()
|
|
173
|
+
schema = CodingDomain.api_dev_schema()
|
|
174
|
+
|
|
175
|
+
agent = Agent(
|
|
176
|
+
name="victor",
|
|
177
|
+
role="Backend QA Specialist",
|
|
178
|
+
description=(
|
|
179
|
+
"Expert in API testing, database validation, performance testing, "
|
|
180
|
+
"and backend robustness. Focuses on edge cases and error handling."
|
|
181
|
+
),
|
|
182
|
+
memory_schema=schema,
|
|
183
|
+
traits=[
|
|
184
|
+
"Security-conscious",
|
|
185
|
+
"Performance-focused",
|
|
186
|
+
"Thorough error case coverage",
|
|
187
|
+
"Data integrity guardian",
|
|
188
|
+
],
|
|
189
|
+
default_actions=[
|
|
190
|
+
"Test authentication first",
|
|
191
|
+
"Verify error responses are informative",
|
|
192
|
+
"Check rate limiting",
|
|
193
|
+
"Validate data persistence",
|
|
194
|
+
],
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
return Harness(setting=setting, agent=agent, alma=alma)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
# =============================================================================
|
|
201
|
+
# RESEARCH DOMAIN
|
|
202
|
+
# =============================================================================
|
|
203
|
+
|
|
204
|
+
class ResearchDomain:
|
|
205
|
+
"""Pre-built configurations for research and analysis agents."""
|
|
206
|
+
|
|
207
|
+
@staticmethod
|
|
208
|
+
def market_research_schema() -> MemorySchema:
|
|
209
|
+
"""Memory schema for market research agents."""
|
|
210
|
+
return MemorySchema(
|
|
211
|
+
domain="market_research",
|
|
212
|
+
description="Market trends, competitive intelligence, and source reliability",
|
|
213
|
+
learnable_categories=[
|
|
214
|
+
"trend_patterns",
|
|
215
|
+
"source_reliability",
|
|
216
|
+
"query_refinements",
|
|
217
|
+
"data_synthesis_patterns",
|
|
218
|
+
"competitor_tracking",
|
|
219
|
+
"market_indicators",
|
|
220
|
+
],
|
|
221
|
+
forbidden_categories=[
|
|
222
|
+
"code_implementation",
|
|
223
|
+
"ui_design",
|
|
224
|
+
"personal_data",
|
|
225
|
+
],
|
|
226
|
+
heuristic_templates=[
|
|
227
|
+
"For {market_segment} research, prioritize {source_type} sources",
|
|
228
|
+
"Query '{refined_query}' yields better results than '{original_query}'",
|
|
229
|
+
"Source {source_name} is {reliability}% accurate for {topic}",
|
|
230
|
+
"Trend pattern: {pattern} typically indicates {outcome}",
|
|
231
|
+
],
|
|
232
|
+
outcome_fields=[
|
|
233
|
+
"query",
|
|
234
|
+
"sources_used",
|
|
235
|
+
"insights_generated",
|
|
236
|
+
"accuracy_score",
|
|
237
|
+
"time_to_insight_ms",
|
|
238
|
+
],
|
|
239
|
+
min_occurrences=5, # Higher threshold for research patterns
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
@staticmethod
|
|
243
|
+
def research_setting() -> Setting:
|
|
244
|
+
"""Default setting for research agents."""
|
|
245
|
+
return Setting(
|
|
246
|
+
name="Research Environment",
|
|
247
|
+
description="Environment for market research and competitive analysis",
|
|
248
|
+
tools=[
|
|
249
|
+
Tool(
|
|
250
|
+
name="web_search",
|
|
251
|
+
description="Search the web for information",
|
|
252
|
+
tool_type=ToolType.SEARCH,
|
|
253
|
+
constraints=["Verify sources", "Note publication dates"],
|
|
254
|
+
),
|
|
255
|
+
Tool(
|
|
256
|
+
name="data_api",
|
|
257
|
+
description="Access structured data APIs (financial, market)",
|
|
258
|
+
tool_type=ToolType.DATA_ACCESS,
|
|
259
|
+
constraints=["Respect rate limits", "Cache responses"],
|
|
260
|
+
),
|
|
261
|
+
Tool(
|
|
262
|
+
name="semantic_search",
|
|
263
|
+
description="Search internal knowledge bases",
|
|
264
|
+
tool_type=ToolType.SEARCH,
|
|
265
|
+
constraints=["Include source citations"],
|
|
266
|
+
),
|
|
267
|
+
Tool(
|
|
268
|
+
name="synthesis",
|
|
269
|
+
description="Combine multiple sources into insights",
|
|
270
|
+
tool_type=ToolType.ANALYSIS,
|
|
271
|
+
constraints=["Note conflicting information", "Confidence levels required"],
|
|
272
|
+
),
|
|
273
|
+
],
|
|
274
|
+
global_constraints=[
|
|
275
|
+
"Always cite sources",
|
|
276
|
+
"Note data freshness",
|
|
277
|
+
"Flag speculative vs factual statements",
|
|
278
|
+
"Respect copyright and terms of service",
|
|
279
|
+
],
|
|
280
|
+
)
|
|
281
|
+
|
|
282
|
+
@staticmethod
|
|
283
|
+
def create_researcher(alma: Any, focus: str = "general") -> Harness:
|
|
284
|
+
"""Create a market research agent."""
|
|
285
|
+
setting = ResearchDomain.research_setting()
|
|
286
|
+
schema = ResearchDomain.market_research_schema()
|
|
287
|
+
|
|
288
|
+
agent = Agent(
|
|
289
|
+
name="researcher",
|
|
290
|
+
role="Market Research Analyst",
|
|
291
|
+
description=(
|
|
292
|
+
f"Expert in {focus} market research, competitive intelligence, "
|
|
293
|
+
"and trend analysis. Synthesizes multiple sources into actionable insights."
|
|
294
|
+
),
|
|
295
|
+
memory_schema=schema,
|
|
296
|
+
traits=[
|
|
297
|
+
"Skeptical of single sources",
|
|
298
|
+
"Quantifies confidence levels",
|
|
299
|
+
"Tracks information provenance",
|
|
300
|
+
"Identifies patterns across data",
|
|
301
|
+
],
|
|
302
|
+
default_actions=[
|
|
303
|
+
"Search multiple sources for corroboration",
|
|
304
|
+
"Check publication dates and author credibility",
|
|
305
|
+
"Note conflicting information",
|
|
306
|
+
"Summarize with confidence levels",
|
|
307
|
+
],
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
return Harness(setting=setting, agent=agent, alma=alma)
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
# =============================================================================
|
|
314
|
+
# CONTENT DOMAIN
|
|
315
|
+
# =============================================================================
|
|
316
|
+
|
|
317
|
+
class ContentDomain:
|
|
318
|
+
"""Pre-built configurations for content creation agents."""
|
|
319
|
+
|
|
320
|
+
@staticmethod
|
|
321
|
+
def marketing_schema() -> MemorySchema:
|
|
322
|
+
"""Memory schema for marketing content agents."""
|
|
323
|
+
return MemorySchema(
|
|
324
|
+
domain="marketing_content",
|
|
325
|
+
description="Marketing copy patterns, engagement metrics, and audience preferences",
|
|
326
|
+
learnable_categories=[
|
|
327
|
+
"headline_patterns",
|
|
328
|
+
"call_to_action_patterns",
|
|
329
|
+
"audience_preferences",
|
|
330
|
+
"engagement_metrics",
|
|
331
|
+
"tone_effectiveness",
|
|
332
|
+
"visual_pairing",
|
|
333
|
+
],
|
|
334
|
+
forbidden_categories=[
|
|
335
|
+
"technical_implementation",
|
|
336
|
+
"pricing_decisions",
|
|
337
|
+
"legal_claims",
|
|
338
|
+
],
|
|
339
|
+
heuristic_templates=[
|
|
340
|
+
"For {audience_segment}, {tone} tone increases engagement by {percent}%",
|
|
341
|
+
"Headline pattern '{pattern}' performs best for {content_type}",
|
|
342
|
+
"Call-to-action '{cta}' converts {rate}% for {context}",
|
|
343
|
+
"Visual style {style} resonates with {audience}",
|
|
344
|
+
],
|
|
345
|
+
outcome_fields=[
|
|
346
|
+
"content_type",
|
|
347
|
+
"target_audience",
|
|
348
|
+
"engagement_rate",
|
|
349
|
+
"conversion_rate",
|
|
350
|
+
"a_b_test_winner",
|
|
351
|
+
],
|
|
352
|
+
min_occurrences=5,
|
|
353
|
+
)
|
|
354
|
+
|
|
355
|
+
@staticmethod
|
|
356
|
+
def documentation_schema() -> MemorySchema:
|
|
357
|
+
"""Memory schema for technical documentation agents."""
|
|
358
|
+
return MemorySchema(
|
|
359
|
+
domain="documentation",
|
|
360
|
+
description="Documentation patterns, clarity metrics, and user comprehension",
|
|
361
|
+
learnable_categories=[
|
|
362
|
+
"explanation_patterns",
|
|
363
|
+
"code_example_patterns",
|
|
364
|
+
"structure_preferences",
|
|
365
|
+
"terminology_choices",
|
|
366
|
+
"diagram_usage",
|
|
367
|
+
],
|
|
368
|
+
forbidden_categories=[
|
|
369
|
+
"marketing_claims",
|
|
370
|
+
"pricing_information",
|
|
371
|
+
"security_details",
|
|
372
|
+
],
|
|
373
|
+
heuristic_templates=[
|
|
374
|
+
"For {concept_complexity}, use {explanation_approach}",
|
|
375
|
+
"Code examples should demonstrate {pattern} for {use_case}",
|
|
376
|
+
"Users understand {term_a} better than {term_b}",
|
|
377
|
+
],
|
|
378
|
+
outcome_fields=[
|
|
379
|
+
"doc_type",
|
|
380
|
+
"reader_level",
|
|
381
|
+
"comprehension_score",
|
|
382
|
+
"time_to_understanding",
|
|
383
|
+
"questions_reduced",
|
|
384
|
+
],
|
|
385
|
+
min_occurrences=3,
|
|
386
|
+
)
|
|
387
|
+
|
|
388
|
+
@staticmethod
|
|
389
|
+
def content_setting() -> Setting:
|
|
390
|
+
"""Default setting for content creation agents."""
|
|
391
|
+
return Setting(
|
|
392
|
+
name="Content Creation Environment",
|
|
393
|
+
description="Environment for creating marketing and documentation content",
|
|
394
|
+
tools=[
|
|
395
|
+
Tool(
|
|
396
|
+
name="trend_search",
|
|
397
|
+
description="Search for trending topics and phrases",
|
|
398
|
+
tool_type=ToolType.SEARCH,
|
|
399
|
+
constraints=["Note trend velocity", "Check regional variations"],
|
|
400
|
+
),
|
|
401
|
+
Tool(
|
|
402
|
+
name="image_search",
|
|
403
|
+
description="Find relevant images and visual assets",
|
|
404
|
+
tool_type=ToolType.SEARCH,
|
|
405
|
+
constraints=["Verify licensing", "Check brand alignment"],
|
|
406
|
+
),
|
|
407
|
+
Tool(
|
|
408
|
+
name="analytics",
|
|
409
|
+
description="Access content performance metrics",
|
|
410
|
+
tool_type=ToolType.ANALYSIS,
|
|
411
|
+
constraints=["Compare against baselines", "Note sample sizes"],
|
|
412
|
+
),
|
|
413
|
+
Tool(
|
|
414
|
+
name="style_check",
|
|
415
|
+
description="Validate content against style guides",
|
|
416
|
+
tool_type=ToolType.ANALYSIS,
|
|
417
|
+
constraints=["Flag deviations", "Suggest alternatives"],
|
|
418
|
+
),
|
|
419
|
+
],
|
|
420
|
+
global_constraints=[
|
|
421
|
+
"Adhere to brand voice guidelines",
|
|
422
|
+
"No unsubstantiated claims",
|
|
423
|
+
"Respect copyright",
|
|
424
|
+
"Include accessibility considerations",
|
|
425
|
+
],
|
|
426
|
+
)
|
|
427
|
+
|
|
428
|
+
@staticmethod
|
|
429
|
+
def create_copywriter(alma: Any) -> Harness:
|
|
430
|
+
"""Create a marketing copywriter agent."""
|
|
431
|
+
setting = ContentDomain.content_setting()
|
|
432
|
+
schema = ContentDomain.marketing_schema()
|
|
433
|
+
|
|
434
|
+
agent = Agent(
|
|
435
|
+
name="copywriter",
|
|
436
|
+
role="Marketing Copywriter",
|
|
437
|
+
description=(
|
|
438
|
+
"Expert in persuasive writing, audience engagement, and brand voice. "
|
|
439
|
+
"Creates compelling content that drives action while staying authentic."
|
|
440
|
+
),
|
|
441
|
+
memory_schema=schema,
|
|
442
|
+
traits=[
|
|
443
|
+
"Audience-first thinking",
|
|
444
|
+
"Data-informed creativity",
|
|
445
|
+
"Brand voice guardian",
|
|
446
|
+
"A/B testing mindset",
|
|
447
|
+
],
|
|
448
|
+
default_actions=[
|
|
449
|
+
"Research target audience first",
|
|
450
|
+
"Generate multiple headline options",
|
|
451
|
+
"Include clear call-to-action",
|
|
452
|
+
"Check against brand guidelines",
|
|
453
|
+
],
|
|
454
|
+
)
|
|
455
|
+
|
|
456
|
+
return Harness(setting=setting, agent=agent, alma=alma)
|
|
457
|
+
|
|
458
|
+
@staticmethod
|
|
459
|
+
def create_documenter(alma: Any) -> Harness:
|
|
460
|
+
"""Create a technical documentation agent."""
|
|
461
|
+
setting = ContentDomain.content_setting()
|
|
462
|
+
schema = ContentDomain.documentation_schema()
|
|
463
|
+
|
|
464
|
+
agent = Agent(
|
|
465
|
+
name="documenter",
|
|
466
|
+
role="Technical Writer",
|
|
467
|
+
description=(
|
|
468
|
+
"Expert in explaining complex concepts clearly. Creates documentation "
|
|
469
|
+
"that helps users succeed with minimal friction."
|
|
470
|
+
),
|
|
471
|
+
memory_schema=schema,
|
|
472
|
+
traits=[
|
|
473
|
+
"Clarity obsessed",
|
|
474
|
+
"User empathy",
|
|
475
|
+
"Example-driven",
|
|
476
|
+
"Progressive disclosure",
|
|
477
|
+
],
|
|
478
|
+
default_actions=[
|
|
479
|
+
"Start with user's goal",
|
|
480
|
+
"Use concrete examples",
|
|
481
|
+
"Include common pitfalls",
|
|
482
|
+
"Link related concepts",
|
|
483
|
+
],
|
|
484
|
+
)
|
|
485
|
+
|
|
486
|
+
return Harness(setting=setting, agent=agent, alma=alma)
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
# =============================================================================
|
|
490
|
+
# OPERATIONS DOMAIN
|
|
491
|
+
# =============================================================================
|
|
492
|
+
|
|
493
|
+
class OperationsDomain:
|
|
494
|
+
"""Pre-built configurations for operations and support agents."""
|
|
495
|
+
|
|
496
|
+
@staticmethod
|
|
497
|
+
def support_schema() -> MemorySchema:
|
|
498
|
+
"""Memory schema for customer support agents."""
|
|
499
|
+
return MemorySchema(
|
|
500
|
+
domain="customer_support",
|
|
501
|
+
description="Issue resolution patterns, customer preferences, and escalation paths",
|
|
502
|
+
learnable_categories=[
|
|
503
|
+
"issue_patterns",
|
|
504
|
+
"resolution_steps",
|
|
505
|
+
"customer_preferences",
|
|
506
|
+
"escalation_triggers",
|
|
507
|
+
"product_knowledge",
|
|
508
|
+
"communication_styles",
|
|
509
|
+
],
|
|
510
|
+
forbidden_categories=[
|
|
511
|
+
"billing_modifications",
|
|
512
|
+
"security_overrides",
|
|
513
|
+
"contract_changes",
|
|
514
|
+
],
|
|
515
|
+
heuristic_templates=[
|
|
516
|
+
"For {issue_type}, try {resolution_steps} first (resolves {rate}%)",
|
|
517
|
+
"Customer {customer_type} prefers {communication_style}",
|
|
518
|
+
"Escalate when {condition} - resolution rate drops after {threshold}",
|
|
519
|
+
"Product issue {issue} is usually caused by {root_cause}",
|
|
520
|
+
],
|
|
521
|
+
outcome_fields=[
|
|
522
|
+
"issue_type",
|
|
523
|
+
"resolution_time_ms",
|
|
524
|
+
"customer_satisfaction",
|
|
525
|
+
"escalated",
|
|
526
|
+
"first_contact_resolution",
|
|
527
|
+
],
|
|
528
|
+
min_occurrences=5,
|
|
529
|
+
)
|
|
530
|
+
|
|
531
|
+
@staticmethod
|
|
532
|
+
def automation_schema() -> MemorySchema:
|
|
533
|
+
"""Memory schema for automation/workflow agents."""
|
|
534
|
+
return MemorySchema(
|
|
535
|
+
domain="automation",
|
|
536
|
+
description="Workflow patterns, optimization opportunities, and failure modes",
|
|
537
|
+
learnable_categories=[
|
|
538
|
+
"workflow_patterns",
|
|
539
|
+
"optimization_opportunities",
|
|
540
|
+
"failure_modes",
|
|
541
|
+
"retry_strategies",
|
|
542
|
+
"resource_usage",
|
|
543
|
+
],
|
|
544
|
+
forbidden_categories=[
|
|
545
|
+
"manual_overrides",
|
|
546
|
+
"security_bypasses",
|
|
547
|
+
"data_deletion",
|
|
548
|
+
],
|
|
549
|
+
heuristic_templates=[
|
|
550
|
+
"Workflow {workflow} fails {rate}% when {condition}",
|
|
551
|
+
"Retry strategy {strategy} succeeds for {error_type} after {attempts} attempts",
|
|
552
|
+
"Resource {resource} peaks at {time} - schedule {action} accordingly",
|
|
553
|
+
],
|
|
554
|
+
outcome_fields=[
|
|
555
|
+
"workflow_name",
|
|
556
|
+
"execution_time_ms",
|
|
557
|
+
"success_rate",
|
|
558
|
+
"resource_usage",
|
|
559
|
+
"error_type",
|
|
560
|
+
],
|
|
561
|
+
min_occurrences=10, # Higher threshold for automation patterns
|
|
562
|
+
)
|
|
563
|
+
|
|
564
|
+
@staticmethod
|
|
565
|
+
def operations_setting() -> Setting:
|
|
566
|
+
"""Default setting for operations agents."""
|
|
567
|
+
return Setting(
|
|
568
|
+
name="Operations Environment",
|
|
569
|
+
description="Environment for customer support and automation tasks",
|
|
570
|
+
tools=[
|
|
571
|
+
Tool(
|
|
572
|
+
name="ticket_system",
|
|
573
|
+
description="Access and update support tickets",
|
|
574
|
+
tool_type=ToolType.DATA_ACCESS,
|
|
575
|
+
constraints=["Log all actions", "Respect SLAs"],
|
|
576
|
+
),
|
|
577
|
+
Tool(
|
|
578
|
+
name="knowledge_base",
|
|
579
|
+
description="Search internal documentation and solutions",
|
|
580
|
+
tool_type=ToolType.SEARCH,
|
|
581
|
+
constraints=["Check article freshness", "Flag outdated content"],
|
|
582
|
+
),
|
|
583
|
+
Tool(
|
|
584
|
+
name="customer_history",
|
|
585
|
+
description="Access customer interaction history",
|
|
586
|
+
tool_type=ToolType.DATA_ACCESS,
|
|
587
|
+
constraints=["Respect privacy", "Only relevant history"],
|
|
588
|
+
),
|
|
589
|
+
Tool(
|
|
590
|
+
name="escalation",
|
|
591
|
+
description="Escalate to human agents or specialists",
|
|
592
|
+
tool_type=ToolType.COMMUNICATION,
|
|
593
|
+
constraints=["Include context", "Note attempted resolutions"],
|
|
594
|
+
),
|
|
595
|
+
],
|
|
596
|
+
global_constraints=[
|
|
597
|
+
"Never share customer data externally",
|
|
598
|
+
"Log all customer interactions",
|
|
599
|
+
"Escalate security concerns immediately",
|
|
600
|
+
"Maintain professional tone",
|
|
601
|
+
],
|
|
602
|
+
)
|
|
603
|
+
|
|
604
|
+
@staticmethod
|
|
605
|
+
def create_support_agent(alma: Any) -> Harness:
|
|
606
|
+
"""Create a customer support agent."""
|
|
607
|
+
setting = OperationsDomain.operations_setting()
|
|
608
|
+
schema = OperationsDomain.support_schema()
|
|
609
|
+
|
|
610
|
+
agent = Agent(
|
|
611
|
+
name="support",
|
|
612
|
+
role="Customer Support Specialist",
|
|
613
|
+
description=(
|
|
614
|
+
"Expert in resolving customer issues efficiently and empathetically. "
|
|
615
|
+
"Balances speed with thoroughness, knows when to escalate."
|
|
616
|
+
),
|
|
617
|
+
memory_schema=schema,
|
|
618
|
+
traits=[
|
|
619
|
+
"Empathetic communication",
|
|
620
|
+
"Efficient problem-solving",
|
|
621
|
+
"Knows when to escalate",
|
|
622
|
+
"Proactive issue prevention",
|
|
623
|
+
],
|
|
624
|
+
default_actions=[
|
|
625
|
+
"Acknowledge the issue",
|
|
626
|
+
"Check known solutions first",
|
|
627
|
+
"Gather necessary context",
|
|
628
|
+
"Follow up to confirm resolution",
|
|
629
|
+
],
|
|
630
|
+
)
|
|
631
|
+
|
|
632
|
+
return Harness(setting=setting, agent=agent, alma=alma)
|
|
633
|
+
|
|
634
|
+
|
|
635
|
+
# =============================================================================
|
|
636
|
+
# FACTORY FUNCTION
|
|
637
|
+
# =============================================================================
|
|
638
|
+
|
|
639
|
+
def create_harness(
|
|
640
|
+
domain: str,
|
|
641
|
+
agent_type: str,
|
|
642
|
+
alma: Any,
|
|
643
|
+
**kwargs,
|
|
644
|
+
) -> Harness:
|
|
645
|
+
"""
|
|
646
|
+
Factory function to create domain-specific harnesses.
|
|
647
|
+
|
|
648
|
+
Args:
|
|
649
|
+
domain: One of "coding", "research", "content", "operations"
|
|
650
|
+
agent_type: Specific agent within domain
|
|
651
|
+
alma: ALMA instance
|
|
652
|
+
**kwargs: Additional configuration
|
|
653
|
+
|
|
654
|
+
Returns:
|
|
655
|
+
Configured Harness instance
|
|
656
|
+
|
|
657
|
+
Examples:
|
|
658
|
+
harness = create_harness("coding", "helena", alma)
|
|
659
|
+
harness = create_harness("research", "researcher", alma, focus="biotech")
|
|
660
|
+
harness = create_harness("content", "copywriter", alma)
|
|
661
|
+
harness = create_harness("operations", "support", alma)
|
|
662
|
+
"""
|
|
663
|
+
factories = {
|
|
664
|
+
"coding": {
|
|
665
|
+
"helena": CodingDomain.create_helena,
|
|
666
|
+
"victor": CodingDomain.create_victor,
|
|
667
|
+
},
|
|
668
|
+
"research": {
|
|
669
|
+
"researcher": lambda a: ResearchDomain.create_researcher(a, kwargs.get("focus", "general")),
|
|
670
|
+
},
|
|
671
|
+
"content": {
|
|
672
|
+
"copywriter": ContentDomain.create_copywriter,
|
|
673
|
+
"documenter": ContentDomain.create_documenter,
|
|
674
|
+
},
|
|
675
|
+
"operations": {
|
|
676
|
+
"support": OperationsDomain.create_support_agent,
|
|
677
|
+
},
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
if domain not in factories:
|
|
681
|
+
raise ValueError(f"Unknown domain: {domain}. Available: {list(factories.keys())}")
|
|
682
|
+
|
|
683
|
+
if agent_type not in factories[domain]:
|
|
684
|
+
raise ValueError(
|
|
685
|
+
f"Unknown agent type '{agent_type}' for domain '{domain}'. "
|
|
686
|
+
f"Available: {list(factories[domain].keys())}"
|
|
687
|
+
)
|
|
688
|
+
|
|
689
|
+
return factories[domain][agent_type](alma)
|