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