attune-ai 2.0.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.
- attune/__init__.py +358 -0
- attune/adaptive/__init__.py +13 -0
- attune/adaptive/task_complexity.py +127 -0
- attune/agent_monitoring.py +414 -0
- attune/cache/__init__.py +117 -0
- attune/cache/base.py +166 -0
- attune/cache/dependency_manager.py +256 -0
- attune/cache/hash_only.py +251 -0
- attune/cache/hybrid.py +457 -0
- attune/cache/storage.py +285 -0
- attune/cache_monitor.py +356 -0
- attune/cache_stats.py +298 -0
- attune/cli/__init__.py +152 -0
- attune/cli/__main__.py +12 -0
- attune/cli/commands/__init__.py +1 -0
- attune/cli/commands/batch.py +264 -0
- attune/cli/commands/cache.py +248 -0
- attune/cli/commands/help.py +331 -0
- attune/cli/commands/info.py +140 -0
- attune/cli/commands/inspect.py +436 -0
- attune/cli/commands/inspection.py +57 -0
- attune/cli/commands/memory.py +48 -0
- attune/cli/commands/metrics.py +92 -0
- attune/cli/commands/orchestrate.py +184 -0
- attune/cli/commands/patterns.py +207 -0
- attune/cli/commands/profiling.py +202 -0
- attune/cli/commands/provider.py +98 -0
- attune/cli/commands/routing.py +285 -0
- attune/cli/commands/setup.py +96 -0
- attune/cli/commands/status.py +235 -0
- attune/cli/commands/sync.py +166 -0
- attune/cli/commands/tier.py +121 -0
- attune/cli/commands/utilities.py +114 -0
- attune/cli/commands/workflow.py +579 -0
- attune/cli/core.py +32 -0
- attune/cli/parsers/__init__.py +68 -0
- attune/cli/parsers/batch.py +118 -0
- attune/cli/parsers/cache.py +65 -0
- attune/cli/parsers/help.py +41 -0
- attune/cli/parsers/info.py +26 -0
- attune/cli/parsers/inspect.py +66 -0
- attune/cli/parsers/metrics.py +42 -0
- attune/cli/parsers/orchestrate.py +61 -0
- attune/cli/parsers/patterns.py +54 -0
- attune/cli/parsers/provider.py +40 -0
- attune/cli/parsers/routing.py +110 -0
- attune/cli/parsers/setup.py +42 -0
- attune/cli/parsers/status.py +47 -0
- attune/cli/parsers/sync.py +31 -0
- attune/cli/parsers/tier.py +33 -0
- attune/cli/parsers/workflow.py +77 -0
- attune/cli/utils/__init__.py +1 -0
- attune/cli/utils/data.py +242 -0
- attune/cli/utils/helpers.py +68 -0
- attune/cli_legacy.py +3957 -0
- attune/cli_minimal.py +1159 -0
- attune/cli_router.py +437 -0
- attune/cli_unified.py +814 -0
- attune/config/__init__.py +66 -0
- attune/config/xml_config.py +286 -0
- attune/config.py +545 -0
- attune/coordination.py +870 -0
- attune/core.py +1511 -0
- attune/core_modules/__init__.py +15 -0
- attune/cost_tracker.py +626 -0
- attune/dashboard/__init__.py +41 -0
- attune/dashboard/app.py +512 -0
- attune/dashboard/simple_server.py +435 -0
- attune/dashboard/standalone_server.py +547 -0
- attune/discovery.py +306 -0
- attune/emergence.py +306 -0
- attune/exceptions.py +123 -0
- attune/feedback_loops.py +373 -0
- attune/hot_reload/README.md +473 -0
- attune/hot_reload/__init__.py +62 -0
- attune/hot_reload/config.py +83 -0
- attune/hot_reload/integration.py +229 -0
- attune/hot_reload/reloader.py +298 -0
- attune/hot_reload/watcher.py +183 -0
- attune/hot_reload/websocket.py +177 -0
- attune/levels.py +577 -0
- attune/leverage_points.py +441 -0
- attune/logging_config.py +261 -0
- attune/mcp/__init__.py +10 -0
- attune/mcp/server.py +506 -0
- attune/memory/__init__.py +237 -0
- attune/memory/claude_memory.py +469 -0
- attune/memory/config.py +224 -0
- attune/memory/control_panel.py +1290 -0
- attune/memory/control_panel_support.py +145 -0
- attune/memory/cross_session.py +845 -0
- attune/memory/edges.py +179 -0
- attune/memory/encryption.py +159 -0
- attune/memory/file_session.py +770 -0
- attune/memory/graph.py +570 -0
- attune/memory/long_term.py +913 -0
- attune/memory/long_term_types.py +99 -0
- attune/memory/mixins/__init__.py +25 -0
- attune/memory/mixins/backend_init_mixin.py +249 -0
- attune/memory/mixins/capabilities_mixin.py +208 -0
- attune/memory/mixins/handoff_mixin.py +208 -0
- attune/memory/mixins/lifecycle_mixin.py +49 -0
- attune/memory/mixins/long_term_mixin.py +352 -0
- attune/memory/mixins/promotion_mixin.py +109 -0
- attune/memory/mixins/short_term_mixin.py +182 -0
- attune/memory/nodes.py +179 -0
- attune/memory/redis_bootstrap.py +540 -0
- attune/memory/security/__init__.py +31 -0
- attune/memory/security/audit_logger.py +932 -0
- attune/memory/security/pii_scrubber.py +640 -0
- attune/memory/security/secrets_detector.py +678 -0
- attune/memory/short_term.py +2192 -0
- attune/memory/simple_storage.py +302 -0
- attune/memory/storage/__init__.py +15 -0
- attune/memory/storage_backend.py +167 -0
- attune/memory/summary_index.py +583 -0
- attune/memory/types.py +446 -0
- attune/memory/unified.py +182 -0
- attune/meta_workflows/__init__.py +74 -0
- attune/meta_workflows/agent_creator.py +248 -0
- attune/meta_workflows/builtin_templates.py +567 -0
- attune/meta_workflows/cli_commands/__init__.py +56 -0
- attune/meta_workflows/cli_commands/agent_commands.py +321 -0
- attune/meta_workflows/cli_commands/analytics_commands.py +442 -0
- attune/meta_workflows/cli_commands/config_commands.py +232 -0
- attune/meta_workflows/cli_commands/memory_commands.py +182 -0
- attune/meta_workflows/cli_commands/template_commands.py +354 -0
- attune/meta_workflows/cli_commands/workflow_commands.py +382 -0
- attune/meta_workflows/cli_meta_workflows.py +59 -0
- attune/meta_workflows/form_engine.py +292 -0
- attune/meta_workflows/intent_detector.py +409 -0
- attune/meta_workflows/models.py +569 -0
- attune/meta_workflows/pattern_learner.py +738 -0
- attune/meta_workflows/plan_generator.py +384 -0
- attune/meta_workflows/session_context.py +397 -0
- attune/meta_workflows/template_registry.py +229 -0
- attune/meta_workflows/workflow.py +984 -0
- attune/metrics/__init__.py +12 -0
- attune/metrics/collector.py +31 -0
- attune/metrics/prompt_metrics.py +194 -0
- attune/models/__init__.py +172 -0
- attune/models/__main__.py +13 -0
- attune/models/adaptive_routing.py +437 -0
- attune/models/auth_cli.py +444 -0
- attune/models/auth_strategy.py +450 -0
- attune/models/cli.py +655 -0
- attune/models/empathy_executor.py +354 -0
- attune/models/executor.py +257 -0
- attune/models/fallback.py +762 -0
- attune/models/provider_config.py +282 -0
- attune/models/registry.py +472 -0
- attune/models/tasks.py +359 -0
- attune/models/telemetry/__init__.py +71 -0
- attune/models/telemetry/analytics.py +594 -0
- attune/models/telemetry/backend.py +196 -0
- attune/models/telemetry/data_models.py +431 -0
- attune/models/telemetry/storage.py +489 -0
- attune/models/token_estimator.py +420 -0
- attune/models/validation.py +280 -0
- attune/monitoring/__init__.py +52 -0
- attune/monitoring/alerts.py +946 -0
- attune/monitoring/alerts_cli.py +448 -0
- attune/monitoring/multi_backend.py +271 -0
- attune/monitoring/otel_backend.py +362 -0
- attune/optimization/__init__.py +19 -0
- attune/optimization/context_optimizer.py +272 -0
- attune/orchestration/__init__.py +67 -0
- attune/orchestration/agent_templates.py +707 -0
- attune/orchestration/config_store.py +499 -0
- attune/orchestration/execution_strategies.py +2111 -0
- attune/orchestration/meta_orchestrator.py +1168 -0
- attune/orchestration/pattern_learner.py +696 -0
- attune/orchestration/real_tools.py +931 -0
- attune/pattern_cache.py +187 -0
- attune/pattern_library.py +542 -0
- attune/patterns/debugging/all_patterns.json +81 -0
- attune/patterns/debugging/workflow_20260107_1770825e.json +77 -0
- attune/patterns/refactoring_memory.json +89 -0
- attune/persistence.py +564 -0
- attune/platform_utils.py +265 -0
- attune/plugins/__init__.py +28 -0
- attune/plugins/base.py +361 -0
- attune/plugins/registry.py +268 -0
- attune/project_index/__init__.py +32 -0
- attune/project_index/cli.py +335 -0
- attune/project_index/index.py +667 -0
- attune/project_index/models.py +504 -0
- attune/project_index/reports.py +474 -0
- attune/project_index/scanner.py +777 -0
- attune/project_index/scanner_parallel.py +291 -0
- attune/prompts/__init__.py +61 -0
- attune/prompts/config.py +77 -0
- attune/prompts/context.py +177 -0
- attune/prompts/parser.py +285 -0
- attune/prompts/registry.py +313 -0
- attune/prompts/templates.py +208 -0
- attune/redis_config.py +302 -0
- attune/redis_memory.py +799 -0
- attune/resilience/__init__.py +56 -0
- attune/resilience/circuit_breaker.py +256 -0
- attune/resilience/fallback.py +179 -0
- attune/resilience/health.py +300 -0
- attune/resilience/retry.py +209 -0
- attune/resilience/timeout.py +135 -0
- attune/routing/__init__.py +43 -0
- attune/routing/chain_executor.py +433 -0
- attune/routing/classifier.py +217 -0
- attune/routing/smart_router.py +234 -0
- attune/routing/workflow_registry.py +343 -0
- attune/scaffolding/README.md +589 -0
- attune/scaffolding/__init__.py +35 -0
- attune/scaffolding/__main__.py +14 -0
- attune/scaffolding/cli.py +240 -0
- attune/scaffolding/templates/base_wizard.py.jinja2 +121 -0
- attune/scaffolding/templates/coach_wizard.py.jinja2 +321 -0
- attune/scaffolding/templates/domain_wizard.py.jinja2 +408 -0
- attune/scaffolding/templates/linear_flow_wizard.py.jinja2 +203 -0
- attune/socratic/__init__.py +256 -0
- attune/socratic/ab_testing.py +958 -0
- attune/socratic/blueprint.py +533 -0
- attune/socratic/cli.py +703 -0
- attune/socratic/collaboration.py +1114 -0
- attune/socratic/domain_templates.py +924 -0
- attune/socratic/embeddings.py +738 -0
- attune/socratic/engine.py +794 -0
- attune/socratic/explainer.py +682 -0
- attune/socratic/feedback.py +772 -0
- attune/socratic/forms.py +629 -0
- attune/socratic/generator.py +732 -0
- attune/socratic/llm_analyzer.py +637 -0
- attune/socratic/mcp_server.py +702 -0
- attune/socratic/session.py +312 -0
- attune/socratic/storage.py +667 -0
- attune/socratic/success.py +730 -0
- attune/socratic/visual_editor.py +860 -0
- attune/socratic/web_ui.py +958 -0
- attune/telemetry/__init__.py +39 -0
- attune/telemetry/agent_coordination.py +475 -0
- attune/telemetry/agent_tracking.py +367 -0
- attune/telemetry/approval_gates.py +545 -0
- attune/telemetry/cli.py +1231 -0
- attune/telemetry/commands/__init__.py +14 -0
- attune/telemetry/commands/dashboard_commands.py +696 -0
- attune/telemetry/event_streaming.py +409 -0
- attune/telemetry/feedback_loop.py +567 -0
- attune/telemetry/usage_tracker.py +591 -0
- attune/templates.py +754 -0
- attune/test_generator/__init__.py +38 -0
- attune/test_generator/__main__.py +14 -0
- attune/test_generator/cli.py +234 -0
- attune/test_generator/generator.py +355 -0
- attune/test_generator/risk_analyzer.py +216 -0
- attune/test_generator/templates/unit_test.py.jinja2 +272 -0
- attune/tier_recommender.py +384 -0
- attune/tools.py +183 -0
- attune/trust/__init__.py +28 -0
- attune/trust/circuit_breaker.py +579 -0
- attune/trust_building.py +527 -0
- attune/validation/__init__.py +19 -0
- attune/validation/xml_validator.py +281 -0
- attune/vscode_bridge.py +173 -0
- attune/workflow_commands.py +780 -0
- attune/workflow_patterns/__init__.py +33 -0
- attune/workflow_patterns/behavior.py +249 -0
- attune/workflow_patterns/core.py +76 -0
- attune/workflow_patterns/output.py +99 -0
- attune/workflow_patterns/registry.py +255 -0
- attune/workflow_patterns/structural.py +288 -0
- attune/workflows/__init__.py +539 -0
- attune/workflows/autonomous_test_gen.py +1268 -0
- attune/workflows/base.py +2667 -0
- attune/workflows/batch_processing.py +342 -0
- attune/workflows/bug_predict.py +1084 -0
- attune/workflows/builder.py +273 -0
- attune/workflows/caching.py +253 -0
- attune/workflows/code_review.py +1048 -0
- attune/workflows/code_review_adapters.py +312 -0
- attune/workflows/code_review_pipeline.py +722 -0
- attune/workflows/config.py +645 -0
- attune/workflows/dependency_check.py +644 -0
- attune/workflows/document_gen/__init__.py +25 -0
- attune/workflows/document_gen/config.py +30 -0
- attune/workflows/document_gen/report_formatter.py +162 -0
- attune/workflows/document_gen/workflow.py +1426 -0
- attune/workflows/document_manager.py +216 -0
- attune/workflows/document_manager_README.md +134 -0
- attune/workflows/documentation_orchestrator.py +1205 -0
- attune/workflows/history.py +510 -0
- attune/workflows/keyboard_shortcuts/__init__.py +39 -0
- attune/workflows/keyboard_shortcuts/generators.py +391 -0
- attune/workflows/keyboard_shortcuts/parsers.py +416 -0
- attune/workflows/keyboard_shortcuts/prompts.py +295 -0
- attune/workflows/keyboard_shortcuts/schema.py +193 -0
- attune/workflows/keyboard_shortcuts/workflow.py +509 -0
- attune/workflows/llm_base.py +363 -0
- attune/workflows/manage_docs.py +87 -0
- attune/workflows/manage_docs_README.md +134 -0
- attune/workflows/manage_documentation.py +821 -0
- attune/workflows/new_sample_workflow1.py +149 -0
- attune/workflows/new_sample_workflow1_README.md +150 -0
- attune/workflows/orchestrated_health_check.py +849 -0
- attune/workflows/orchestrated_release_prep.py +600 -0
- attune/workflows/output.py +413 -0
- attune/workflows/perf_audit.py +863 -0
- attune/workflows/pr_review.py +762 -0
- attune/workflows/progress.py +785 -0
- attune/workflows/progress_server.py +322 -0
- attune/workflows/progressive/README 2.md +454 -0
- attune/workflows/progressive/README.md +454 -0
- attune/workflows/progressive/__init__.py +82 -0
- attune/workflows/progressive/cli.py +219 -0
- attune/workflows/progressive/core.py +488 -0
- attune/workflows/progressive/orchestrator.py +723 -0
- attune/workflows/progressive/reports.py +520 -0
- attune/workflows/progressive/telemetry.py +274 -0
- attune/workflows/progressive/test_gen.py +495 -0
- attune/workflows/progressive/workflow.py +589 -0
- attune/workflows/refactor_plan.py +694 -0
- attune/workflows/release_prep.py +895 -0
- attune/workflows/release_prep_crew.py +969 -0
- attune/workflows/research_synthesis.py +404 -0
- attune/workflows/routing.py +168 -0
- attune/workflows/secure_release.py +593 -0
- attune/workflows/security_adapters.py +297 -0
- attune/workflows/security_audit.py +1329 -0
- attune/workflows/security_audit_phase3.py +355 -0
- attune/workflows/seo_optimization.py +633 -0
- attune/workflows/step_config.py +234 -0
- attune/workflows/telemetry_mixin.py +269 -0
- attune/workflows/test5.py +125 -0
- attune/workflows/test5_README.md +158 -0
- attune/workflows/test_coverage_boost_crew.py +849 -0
- attune/workflows/test_gen/__init__.py +52 -0
- attune/workflows/test_gen/ast_analyzer.py +249 -0
- attune/workflows/test_gen/config.py +88 -0
- attune/workflows/test_gen/data_models.py +38 -0
- attune/workflows/test_gen/report_formatter.py +289 -0
- attune/workflows/test_gen/test_templates.py +381 -0
- attune/workflows/test_gen/workflow.py +655 -0
- attune/workflows/test_gen.py +54 -0
- attune/workflows/test_gen_behavioral.py +477 -0
- attune/workflows/test_gen_parallel.py +341 -0
- attune/workflows/test_lifecycle.py +526 -0
- attune/workflows/test_maintenance.py +627 -0
- attune/workflows/test_maintenance_cli.py +590 -0
- attune/workflows/test_maintenance_crew.py +840 -0
- attune/workflows/test_runner.py +622 -0
- attune/workflows/tier_tracking.py +531 -0
- attune/workflows/xml_enhanced_crew.py +285 -0
- attune_ai-2.0.0.dist-info/METADATA +1026 -0
- attune_ai-2.0.0.dist-info/RECORD +457 -0
- attune_ai-2.0.0.dist-info/WHEEL +5 -0
- attune_ai-2.0.0.dist-info/entry_points.txt +26 -0
- attune_ai-2.0.0.dist-info/licenses/LICENSE +201 -0
- attune_ai-2.0.0.dist-info/licenses/LICENSE_CHANGE_ANNOUNCEMENT.md +101 -0
- attune_ai-2.0.0.dist-info/top_level.txt +5 -0
- attune_healthcare/__init__.py +13 -0
- attune_healthcare/monitors/__init__.py +9 -0
- attune_healthcare/monitors/clinical_protocol_monitor.py +315 -0
- attune_healthcare/monitors/monitoring/__init__.py +44 -0
- attune_healthcare/monitors/monitoring/protocol_checker.py +300 -0
- attune_healthcare/monitors/monitoring/protocol_loader.py +214 -0
- attune_healthcare/monitors/monitoring/sensor_parsers.py +306 -0
- attune_healthcare/monitors/monitoring/trajectory_analyzer.py +389 -0
- attune_llm/README.md +553 -0
- attune_llm/__init__.py +28 -0
- attune_llm/agent_factory/__init__.py +53 -0
- attune_llm/agent_factory/adapters/__init__.py +85 -0
- attune_llm/agent_factory/adapters/autogen_adapter.py +312 -0
- attune_llm/agent_factory/adapters/crewai_adapter.py +483 -0
- attune_llm/agent_factory/adapters/haystack_adapter.py +298 -0
- attune_llm/agent_factory/adapters/langchain_adapter.py +362 -0
- attune_llm/agent_factory/adapters/langgraph_adapter.py +333 -0
- attune_llm/agent_factory/adapters/native.py +228 -0
- attune_llm/agent_factory/adapters/wizard_adapter.py +423 -0
- attune_llm/agent_factory/base.py +305 -0
- attune_llm/agent_factory/crews/__init__.py +67 -0
- attune_llm/agent_factory/crews/code_review.py +1113 -0
- attune_llm/agent_factory/crews/health_check.py +1262 -0
- attune_llm/agent_factory/crews/refactoring.py +1128 -0
- attune_llm/agent_factory/crews/security_audit.py +1018 -0
- attune_llm/agent_factory/decorators.py +287 -0
- attune_llm/agent_factory/factory.py +558 -0
- attune_llm/agent_factory/framework.py +193 -0
- attune_llm/agent_factory/memory_integration.py +328 -0
- attune_llm/agent_factory/resilient.py +320 -0
- attune_llm/agents_md/__init__.py +22 -0
- attune_llm/agents_md/loader.py +218 -0
- attune_llm/agents_md/parser.py +271 -0
- attune_llm/agents_md/registry.py +307 -0
- attune_llm/claude_memory.py +466 -0
- attune_llm/cli/__init__.py +8 -0
- attune_llm/cli/sync_claude.py +487 -0
- attune_llm/code_health.py +1313 -0
- attune_llm/commands/__init__.py +51 -0
- attune_llm/commands/context.py +375 -0
- attune_llm/commands/loader.py +301 -0
- attune_llm/commands/models.py +231 -0
- attune_llm/commands/parser.py +371 -0
- attune_llm/commands/registry.py +429 -0
- attune_llm/config/__init__.py +29 -0
- attune_llm/config/unified.py +291 -0
- attune_llm/context/__init__.py +22 -0
- attune_llm/context/compaction.py +455 -0
- attune_llm/context/manager.py +434 -0
- attune_llm/contextual_patterns.py +361 -0
- attune_llm/core.py +907 -0
- attune_llm/git_pattern_extractor.py +435 -0
- attune_llm/hooks/__init__.py +24 -0
- attune_llm/hooks/config.py +306 -0
- attune_llm/hooks/executor.py +289 -0
- attune_llm/hooks/registry.py +302 -0
- attune_llm/hooks/scripts/__init__.py +39 -0
- attune_llm/hooks/scripts/evaluate_session.py +201 -0
- attune_llm/hooks/scripts/first_time_init.py +285 -0
- attune_llm/hooks/scripts/pre_compact.py +207 -0
- attune_llm/hooks/scripts/session_end.py +183 -0
- attune_llm/hooks/scripts/session_start.py +163 -0
- attune_llm/hooks/scripts/suggest_compact.py +225 -0
- attune_llm/learning/__init__.py +30 -0
- attune_llm/learning/evaluator.py +438 -0
- attune_llm/learning/extractor.py +514 -0
- attune_llm/learning/storage.py +560 -0
- attune_llm/levels.py +227 -0
- attune_llm/pattern_confidence.py +414 -0
- attune_llm/pattern_resolver.py +272 -0
- attune_llm/pattern_summary.py +350 -0
- attune_llm/providers.py +967 -0
- attune_llm/routing/__init__.py +32 -0
- attune_llm/routing/model_router.py +362 -0
- attune_llm/security/IMPLEMENTATION_SUMMARY.md +413 -0
- attune_llm/security/PHASE2_COMPLETE.md +384 -0
- attune_llm/security/PHASE2_SECRETS_DETECTOR_COMPLETE.md +271 -0
- attune_llm/security/QUICK_REFERENCE.md +316 -0
- attune_llm/security/README.md +262 -0
- attune_llm/security/__init__.py +62 -0
- attune_llm/security/audit_logger.py +929 -0
- attune_llm/security/audit_logger_example.py +152 -0
- attune_llm/security/pii_scrubber.py +640 -0
- attune_llm/security/secrets_detector.py +678 -0
- attune_llm/security/secrets_detector_example.py +304 -0
- attune_llm/security/secure_memdocs.py +1192 -0
- attune_llm/security/secure_memdocs_example.py +278 -0
- attune_llm/session_status.py +745 -0
- attune_llm/state.py +246 -0
- attune_llm/utils/__init__.py +5 -0
- attune_llm/utils/tokens.py +349 -0
- attune_software/SOFTWARE_PLUGIN_README.md +57 -0
- attune_software/__init__.py +13 -0
- attune_software/cli/__init__.py +120 -0
- attune_software/cli/inspect.py +362 -0
- attune_software/cli.py +574 -0
- attune_software/plugin.py +188 -0
- workflow_scaffolding/__init__.py +11 -0
- workflow_scaffolding/__main__.py +12 -0
- workflow_scaffolding/cli.py +206 -0
- workflow_scaffolding/generator.py +265 -0
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
"""XML-Enhanced Agent and Task Templates for CrewAI Workflows
|
|
2
|
+
|
|
3
|
+
This module provides reusable base classes for creating XML-enhanced CrewAI
|
|
4
|
+
agents and tasks based on Anthropic's prompting best practices.
|
|
5
|
+
|
|
6
|
+
Benefits:
|
|
7
|
+
- 40-60% reduction in misinterpreted instructions
|
|
8
|
+
- 30-50% better output consistency
|
|
9
|
+
- 20-30% fewer retry attempts
|
|
10
|
+
- Better debugging with separated thinking/answer
|
|
11
|
+
|
|
12
|
+
Usage:
|
|
13
|
+
from attune.workflows.xml_enhanced_crew import XMLAgent, XMLTask, parse_xml_response
|
|
14
|
+
|
|
15
|
+
agent = XMLAgent(
|
|
16
|
+
role="Documentation Analyst",
|
|
17
|
+
goal="Scan codebase for documentation gaps",
|
|
18
|
+
backstory="Expert in code documentation best practices"
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
task = XMLTask(
|
|
22
|
+
description="Analyze Python files for missing docstrings",
|
|
23
|
+
expected_output="JSON list of files with missing documentation",
|
|
24
|
+
agent=agent
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
Copyright 2026 Smart-AI-Memory
|
|
28
|
+
Licensed under Fair Source License 0.9
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
import re
|
|
32
|
+
from dataclasses import dataclass, field
|
|
33
|
+
from typing import Any
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@dataclass
|
|
37
|
+
class XMLAgent:
|
|
38
|
+
"""Agent with XML-enhanced prompting (Anthropic best practice).
|
|
39
|
+
|
|
40
|
+
This class generates structured prompts using XML tags for better clarity
|
|
41
|
+
and reduces ambiguity in agent instructions.
|
|
42
|
+
|
|
43
|
+
Attributes:
|
|
44
|
+
role: The agent's role (e.g., "Documentation Analyst")
|
|
45
|
+
goal: What the agent aims to achieve
|
|
46
|
+
backstory: Domain expertise and personality
|
|
47
|
+
expertise_level: Level of expertise (expert, world-class, etc.)
|
|
48
|
+
use_xml_structure: Enable/disable XML formatting (default: True)
|
|
49
|
+
custom_instructions: Additional instructions to append
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
role: str
|
|
53
|
+
goal: str
|
|
54
|
+
backstory: str
|
|
55
|
+
expertise_level: str = "expert"
|
|
56
|
+
use_xml_structure: bool = True
|
|
57
|
+
custom_instructions: list[str] = field(default_factory=list)
|
|
58
|
+
|
|
59
|
+
def get_system_prompt(self) -> str:
|
|
60
|
+
"""Generate XML-enhanced system prompt for this agent.
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
Structured prompt with XML tags for role, goal, backstory, etc.
|
|
64
|
+
"""
|
|
65
|
+
if not self.use_xml_structure:
|
|
66
|
+
# Legacy format for backward compatibility
|
|
67
|
+
return self._get_legacy_prompt()
|
|
68
|
+
|
|
69
|
+
# XML-enhanced format (Anthropic best practice)
|
|
70
|
+
instructions = [
|
|
71
|
+
"Carefully review all provided context data",
|
|
72
|
+
"Think through your analysis step-by-step",
|
|
73
|
+
"Provide thorough, actionable analysis",
|
|
74
|
+
"Be specific and cite file paths when relevant",
|
|
75
|
+
"Structure your output according to the requested format",
|
|
76
|
+
]
|
|
77
|
+
|
|
78
|
+
# Add custom instructions
|
|
79
|
+
instructions.extend(self.custom_instructions)
|
|
80
|
+
|
|
81
|
+
instructions_text = "\n".join(f"{i}. {inst}" for i, inst in enumerate(instructions, 1))
|
|
82
|
+
|
|
83
|
+
return f"""<agent_role>
|
|
84
|
+
You are a {self.role} with {self.expertise_level}-level expertise.
|
|
85
|
+
</agent_role>
|
|
86
|
+
|
|
87
|
+
<agent_goal>
|
|
88
|
+
{self.goal}
|
|
89
|
+
</agent_goal>
|
|
90
|
+
|
|
91
|
+
<agent_backstory>
|
|
92
|
+
{self.backstory}
|
|
93
|
+
</agent_backstory>
|
|
94
|
+
|
|
95
|
+
<instructions>
|
|
96
|
+
{instructions_text}
|
|
97
|
+
</instructions>
|
|
98
|
+
|
|
99
|
+
<output_structure>
|
|
100
|
+
Always structure your response as:
|
|
101
|
+
|
|
102
|
+
<thinking>
|
|
103
|
+
[Your step-by-step reasoning process]
|
|
104
|
+
- What you observe in the context
|
|
105
|
+
- How you analyze the situation
|
|
106
|
+
- What conclusions you draw
|
|
107
|
+
</thinking>
|
|
108
|
+
|
|
109
|
+
<answer>
|
|
110
|
+
[Your final output in the requested format]
|
|
111
|
+
</answer>
|
|
112
|
+
</output_structure>"""
|
|
113
|
+
|
|
114
|
+
def _get_legacy_prompt(self) -> str:
|
|
115
|
+
"""Generate legacy non-XML prompt for backward compatibility."""
|
|
116
|
+
return f"""You are a {self.role} with {self.expertise_level}-level expertise.
|
|
117
|
+
|
|
118
|
+
Goal: {self.goal}
|
|
119
|
+
|
|
120
|
+
Background: {self.backstory}
|
|
121
|
+
|
|
122
|
+
Provide thorough, actionable analysis. Be specific and cite file paths when relevant."""
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
@dataclass
|
|
126
|
+
class XMLTask:
|
|
127
|
+
"""Task with XML-enhanced prompting (Anthropic best practice).
|
|
128
|
+
|
|
129
|
+
This class generates structured task prompts using XML tags to clearly
|
|
130
|
+
separate task description, context, and expected output.
|
|
131
|
+
|
|
132
|
+
Attributes:
|
|
133
|
+
description: What the task entails
|
|
134
|
+
expected_output: Format and content of expected output
|
|
135
|
+
agent: The XMLAgent assigned to this task
|
|
136
|
+
examples: Optional list of example inputs/outputs
|
|
137
|
+
"""
|
|
138
|
+
|
|
139
|
+
description: str
|
|
140
|
+
expected_output: str
|
|
141
|
+
agent: XMLAgent
|
|
142
|
+
examples: list[dict[str, Any]] = field(default_factory=list)
|
|
143
|
+
|
|
144
|
+
def get_user_prompt(self, context: dict) -> str:
|
|
145
|
+
"""Generate XML-enhanced user prompt for this task.
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
context: Dictionary of context data for the task
|
|
149
|
+
|
|
150
|
+
Returns:
|
|
151
|
+
Structured prompt with XML tags for description, context, etc.
|
|
152
|
+
"""
|
|
153
|
+
if not self.agent.use_xml_structure:
|
|
154
|
+
# Legacy format for backward compatibility
|
|
155
|
+
return self._get_legacy_prompt(context)
|
|
156
|
+
|
|
157
|
+
# XML-enhanced format (Anthropic best practice)
|
|
158
|
+
# Build structured context with proper XML tags
|
|
159
|
+
context_sections = []
|
|
160
|
+
for key, value in context.items():
|
|
161
|
+
if value:
|
|
162
|
+
# Use underscores for tag names (valid XML)
|
|
163
|
+
tag_name = key.replace(" ", "_").replace("-", "_").lower()
|
|
164
|
+
# Wrap in appropriate tags
|
|
165
|
+
context_sections.append(f"<{tag_name}>\n{value}\n</{tag_name}>")
|
|
166
|
+
|
|
167
|
+
context_xml = "\n".join(context_sections)
|
|
168
|
+
|
|
169
|
+
# Build examples XML if provided
|
|
170
|
+
examples_xml = ""
|
|
171
|
+
if self.examples:
|
|
172
|
+
examples_xml = "<examples>\n"
|
|
173
|
+
for i, ex in enumerate(self.examples, 1):
|
|
174
|
+
examples_xml += f'<example number="{i}">\n'
|
|
175
|
+
examples_xml += f"<input>\n{ex.get('input', '')}\n</input>\n"
|
|
176
|
+
examples_xml += f"<expected_output>\n{ex.get('output', '')}\n</expected_output>\n"
|
|
177
|
+
examples_xml += "</example>\n"
|
|
178
|
+
examples_xml += "</examples>\n\n"
|
|
179
|
+
|
|
180
|
+
return f"""{examples_xml}<task_description>
|
|
181
|
+
{self.description}
|
|
182
|
+
</task_description>
|
|
183
|
+
|
|
184
|
+
<context>
|
|
185
|
+
{context_xml}
|
|
186
|
+
</context>
|
|
187
|
+
|
|
188
|
+
<expected_output>
|
|
189
|
+
{self.expected_output}
|
|
190
|
+
</expected_output>
|
|
191
|
+
|
|
192
|
+
<instructions>
|
|
193
|
+
1. Review all context data in the <context> tags above
|
|
194
|
+
2. Structure your response using <thinking> and <answer> tags as defined in your system prompt
|
|
195
|
+
3. Match the expected output format exactly
|
|
196
|
+
4. Be thorough and specific in your analysis
|
|
197
|
+
{"5. Use the examples above as a guide for output structure" if self.examples else ""}
|
|
198
|
+
</instructions>"""
|
|
199
|
+
|
|
200
|
+
def _get_legacy_prompt(self, context: dict) -> str:
|
|
201
|
+
"""Generate legacy non-XML prompt for backward compatibility."""
|
|
202
|
+
context_str = "\n".join(f"- {k}: {v}" for k, v in context.items() if v)
|
|
203
|
+
return f"""{self.description}
|
|
204
|
+
|
|
205
|
+
Context:
|
|
206
|
+
{context_str}
|
|
207
|
+
|
|
208
|
+
Expected output format: {self.expected_output}"""
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def parse_xml_response(response: str) -> dict[str, Any]:
|
|
212
|
+
"""Parse XML-structured agent response.
|
|
213
|
+
|
|
214
|
+
Extracts <thinking> and <answer> tags from agent responses for better
|
|
215
|
+
debugging and transparency.
|
|
216
|
+
|
|
217
|
+
Args:
|
|
218
|
+
response: Raw agent response potentially containing XML tags
|
|
219
|
+
|
|
220
|
+
Returns:
|
|
221
|
+
Dictionary with:
|
|
222
|
+
- thinking: Agent's reasoning process (empty if not found)
|
|
223
|
+
- answer: Agent's final output (or full response if no tags)
|
|
224
|
+
- raw: Original unprocessed response
|
|
225
|
+
- has_structure: True if both thinking and answer tags found
|
|
226
|
+
|
|
227
|
+
Example:
|
|
228
|
+
>>> response = "<thinking>I analyzed...</thinking><answer>Result</answer>"
|
|
229
|
+
>>> parsed = parse_xml_response(response)
|
|
230
|
+
>>> parsed['thinking']
|
|
231
|
+
'I analyzed...'
|
|
232
|
+
>>> parsed['answer']
|
|
233
|
+
'Result'
|
|
234
|
+
>>> parsed['has_structure']
|
|
235
|
+
True
|
|
236
|
+
"""
|
|
237
|
+
thinking_match = re.search(r"<thinking>(.*?)</thinking>", response, re.DOTALL)
|
|
238
|
+
answer_match = re.search(r"<answer>(.*?)</answer>", response, re.DOTALL)
|
|
239
|
+
|
|
240
|
+
return {
|
|
241
|
+
"thinking": thinking_match.group(1).strip() if thinking_match else "",
|
|
242
|
+
"answer": answer_match.group(1).strip() if answer_match else response.strip(),
|
|
243
|
+
"raw": response,
|
|
244
|
+
"has_structure": bool(thinking_match and answer_match),
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def extract_json_from_answer(answer: str) -> dict | None:
|
|
249
|
+
"""Extract JSON from answer tag if present.
|
|
250
|
+
|
|
251
|
+
Attempts to parse JSON from code blocks or the entire answer.
|
|
252
|
+
|
|
253
|
+
Args:
|
|
254
|
+
answer: The answer portion of a parsed response
|
|
255
|
+
|
|
256
|
+
Returns:
|
|
257
|
+
Parsed JSON dict if found, None otherwise
|
|
258
|
+
|
|
259
|
+
Example:
|
|
260
|
+
>>> answer = "Here's the result: ```json\\n{'status': 'ok'}\\n```"
|
|
261
|
+
>>> extract_json_from_answer(answer)
|
|
262
|
+
{'status': 'ok'}
|
|
263
|
+
"""
|
|
264
|
+
import json
|
|
265
|
+
|
|
266
|
+
# Try to find JSON in code blocks first
|
|
267
|
+
json_match = re.search(r"```json\s*(.*?)\s*```", answer, re.DOTALL)
|
|
268
|
+
if json_match:
|
|
269
|
+
try:
|
|
270
|
+
result = json.loads(json_match.group(1))
|
|
271
|
+
return result if isinstance(result, dict) else None
|
|
272
|
+
except json.JSONDecodeError:
|
|
273
|
+
pass
|
|
274
|
+
|
|
275
|
+
# Try to parse entire answer as JSON
|
|
276
|
+
try:
|
|
277
|
+
result = json.loads(answer)
|
|
278
|
+
return result if isinstance(result, dict) else None
|
|
279
|
+
except json.JSONDecodeError:
|
|
280
|
+
return None
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
# Backward compatibility aliases
|
|
284
|
+
Agent = XMLAgent
|
|
285
|
+
Task = XMLTask
|