symfonic-core 4.9.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.
- symfonic/agent/__init__.py +66 -0
- symfonic/agent/cli/__init__.py +1 -0
- symfonic/agent/cli/main.py +119 -0
- symfonic/agent/config.py +103 -0
- symfonic/agent/domain.py +74 -0
- symfonic/agent/engine.py +1496 -0
- symfonic/agent/factory.py +161 -0
- symfonic/agent/fastapi/__init__.py +4 -0
- symfonic/agent/fastapi/dependencies.py +45 -0
- symfonic/agent/fastapi/router.py +531 -0
- symfonic/agent/observability.py +154 -0
- symfonic/agent/prompts/__init__.py +16 -0
- symfonic/agent/prompts/db_section.py +167 -0
- symfonic/agent/prompts/extraction_prompt.py +107 -0
- symfonic/agent/prompts/system_prompt.py +159 -0
- symfonic/agent/prompts/templates/__init__.py +1 -0
- symfonic/agent/prompts/templates/extraction.txt +148 -0
- symfonic/agent/prompts/templates/hms_system.txt +118 -0
- symfonic/agent/scheduler.py +143 -0
- symfonic/agent/sessions.py +84 -0
- symfonic/agent/types.py +185 -0
- symfonic/core/__init__.py +56 -0
- symfonic/core/agents/__init__.py +5 -0
- symfonic/core/agents/in_memory.py +35 -0
- symfonic/core/agents/loader.py +14 -0
- symfonic/core/agents/schema.py +26 -0
- symfonic/core/callbacks/__init__.py +7 -0
- symfonic/core/callbacks/manager.py +79 -0
- symfonic/core/callbacks/noop.py +37 -0
- symfonic/core/callbacks/protocol.py +36 -0
- symfonic/core/capabilities/__init__.py +10 -0
- symfonic/core/capabilities/firecrawl.py +73 -0
- symfonic/core/capabilities/openai_search.py +75 -0
- symfonic/core/capabilities/protocols.py +43 -0
- symfonic/core/config.py +61 -0
- symfonic/core/contracts/__init__.py +47 -0
- symfonic/core/contracts/callbacks.py +58 -0
- symfonic/core/contracts/errors.py +61 -0
- symfonic/core/contracts/types.py +108 -0
- symfonic/core/deps.py +145 -0
- symfonic/core/documents/__init__.py +5 -0
- symfonic/core/documents/in_memory.py +44 -0
- symfonic/core/documents/loader.py +14 -0
- symfonic/core/documents/schema.py +5 -0
- symfonic/core/documents/truncation.py +21 -0
- symfonic/core/edges/__init__.py +1 -0
- symfonic/core/edges/tool_condition.py +27 -0
- symfonic/core/events.py +28 -0
- symfonic/core/graph.py +142 -0
- symfonic/core/learning/__init__.py +12 -0
- symfonic/core/learning/consolidation.py +176 -0
- symfonic/core/learning/models.py +33 -0
- symfonic/core/learning/phases.py +329 -0
- symfonic/core/learning/refiner.py +154 -0
- symfonic/core/logging/__init__.py +6 -0
- symfonic/core/logging/console.py +34 -0
- symfonic/core/logging/protocol.py +22 -0
- symfonic/core/models.py +51 -0
- symfonic/core/nodes/__init__.py +1 -0
- symfonic/core/nodes/compaction.py +116 -0
- symfonic/core/nodes/context_injection.py +102 -0
- symfonic/core/nodes/react.py +143 -0
- symfonic/core/observability/__init__.py +19 -0
- symfonic/core/observability/decorators.py +147 -0
- symfonic/core/observability/hooks.py +68 -0
- symfonic/core/observability/protocol.py +73 -0
- symfonic/core/orchestration.py +28 -0
- symfonic/core/plugins/__init__.py +15 -0
- symfonic/core/plugins/base.py +73 -0
- symfonic/core/plugins/section.py +76 -0
- symfonic/core/presets.py +116 -0
- symfonic/core/prompt/__init__.py +6 -0
- symfonic/core/prompt/_timeout.py +21 -0
- symfonic/core/prompt/builder.py +132 -0
- symfonic/core/prompt/caching.py +50 -0
- symfonic/core/prompt/sections.py +130 -0
- symfonic/core/protocols.py +128 -0
- symfonic/core/providers.py +56 -0
- symfonic/core/py.typed +0 -0
- symfonic/core/resilience.py +21 -0
- symfonic/core/runtime.py +255 -0
- symfonic/core/scope.py +34 -0
- symfonic/core/skills/__init__.py +5 -0
- symfonic/core/skills/filter.py +15 -0
- symfonic/core/skills/formatter.py +15 -0
- symfonic/core/skills/in_memory.py +29 -0
- symfonic/core/skills/loader.py +31 -0
- symfonic/core/skills/markdown_utils.py +15 -0
- symfonic/core/skills/schema.py +5 -0
- symfonic/core/state.py +60 -0
- symfonic/core/streaming/__init__.py +30 -0
- symfonic/core/streaming/adapters/__init__.py +6 -0
- symfonic/core/streaming/adapters/_shared.py +12 -0
- symfonic/core/streaming/adapters/anthropic_adapter.py +112 -0
- symfonic/core/streaming/adapters/openai_adapter.py +96 -0
- symfonic/core/streaming/event_processor.py +37 -0
- symfonic/core/streaming/transpiler.py +216 -0
- symfonic/core/testing/__init__.py +76 -0
- symfonic/core/tool_interface.py +76 -0
- symfonic/core/tools/__init__.py +1 -0
- symfonic/core/tools/_resolve.py +60 -0
- symfonic/core/tools/agent_tools.py +39 -0
- symfonic/core/tools/chart_tools.py +23 -0
- symfonic/core/tools/helpers.py +21 -0
- symfonic/core/tools/memory_tools.py +48 -0
- symfonic/core/tools/registry.py +197 -0
- symfonic/core/tools/skill_tools.py +43 -0
- symfonic/core/tools/web_tools.py +43 -0
- symfonic/infra/__init__.py +22 -0
- symfonic/infra/protocols.py +121 -0
- symfonic/infra/trace.py +168 -0
- symfonic/knowledge/__init__.py +18 -0
- symfonic/knowledge/adapters/__init__.py +16 -0
- symfonic/knowledge/adapters/chroma.py +117 -0
- symfonic/knowledge/models.py +41 -0
- symfonic/knowledge/protocols.py +51 -0
- symfonic/memory/__init__.py +54 -0
- symfonic/memory/_internal/__init__.py +0 -0
- symfonic/memory/_internal/extraction/__init__.py +1 -0
- symfonic/memory/_internal/extraction/service.py +93 -0
- symfonic/memory/_internal/llm/__init__.py +1 -0
- symfonic/memory/_internal/llm/response_parser.py +36 -0
- symfonic/memory/backends/__init__.py +14 -0
- symfonic/memory/backends/chroma.py +108 -0
- symfonic/memory/backends/in_memory.py +232 -0
- symfonic/memory/backends/mongodb.py +375 -0
- symfonic/memory/backends/pool.py +122 -0
- symfonic/memory/backends/postgres_graph.py +353 -0
- symfonic/memory/backends/postgres_vector.py +142 -0
- symfonic/memory/compaction/__init__.py +1 -0
- symfonic/memory/compaction/engine.py +129 -0
- symfonic/memory/compaction/strategies.py +68 -0
- symfonic/memory/graph/__init__.py +1 -0
- symfonic/memory/graph/scoring.py +141 -0
- symfonic/memory/graph/store.py +125 -0
- symfonic/memory/graph/traversal.py +125 -0
- symfonic/memory/janitor.py +269 -0
- symfonic/memory/layers/__init__.py +18 -0
- symfonic/memory/layers/episodic.py +127 -0
- symfonic/memory/layers/procedural/__init__.py +11 -0
- symfonic/memory/layers/procedural/catalog.py +63 -0
- symfonic/memory/layers/procedural/layer.py +123 -0
- symfonic/memory/layers/procedural/router.py +143 -0
- symfonic/memory/layers/prospective.py +106 -0
- symfonic/memory/layers/semantic.py +127 -0
- symfonic/memory/layers/working.py +123 -0
- symfonic/memory/models/__init__.py +21 -0
- symfonic/memory/models/context.py +84 -0
- symfonic/memory/models/edge.py +47 -0
- symfonic/memory/models/entry.py +74 -0
- symfonic/memory/models/node.py +60 -0
- symfonic/memory/models/operation.py +72 -0
- symfonic/memory/orchestrator/__init__.py +1 -0
- symfonic/memory/orchestrator/config.py +98 -0
- symfonic/memory/orchestrator/factory.py +303 -0
- symfonic/memory/orchestrator/orchestrator.py +227 -0
- symfonic/memory/prompts/__init__.py +42 -0
- symfonic/memory/prompts/compaction.txt +46 -0
- symfonic/memory/prompts/router.txt +27 -0
- symfonic/memory/prompts/system.txt +64 -0
- symfonic/memory/protocols.py +204 -0
- symfonic/memory/py.typed +0 -0
- symfonic/memory/retrieval/__init__.py +1 -0
- symfonic/memory/retrieval/discovery.py +110 -0
- symfonic/memory/retrieval/engine.py +186 -0
- symfonic/memory/retrieval/filters.py +60 -0
- symfonic/memory/retrieval/spreading.py +111 -0
- symfonic/memory/types.py +106 -0
- symfonic/tools/__init__.py +1 -0
- symfonic/tools/learning.py +103 -0
- symfonic/tools/mcp/__init__.py +20 -0
- symfonic/tools/mcp/models.py +40 -0
- symfonic/tools/mcp/protocol.py +58 -0
- symfonic/tools/mcp/provider.py +272 -0
- symfonic_core-4.9.0.dist-info/METADATA +289 -0
- symfonic_core-4.9.0.dist-info/RECORD +178 -0
- symfonic_core-4.9.0.dist-info/WHEEL +4 -0
- symfonic_core-4.9.0.dist-info/entry_points.txt +2 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""symfonic.agent -- High-level orchestration layer for multi-memory agents.
|
|
2
|
+
|
|
3
|
+
Integrates symfonic.core (execution engine) and symfonic.memory (5-layer HMS)
|
|
4
|
+
into a unified, engine-first Python module with an optional FastAPI bridge.
|
|
5
|
+
|
|
6
|
+
Public API re-exports. Internal modules should not be imported directly.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from typing import TYPE_CHECKING
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from symfonic.agent.types import (
|
|
15
|
+
AgentRequest,
|
|
16
|
+
AgentResponse,
|
|
17
|
+
FrameworkTenantScope,
|
|
18
|
+
StreamChunk,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
__all__ = [
|
|
22
|
+
"AgentRequest",
|
|
23
|
+
"AgentResponse",
|
|
24
|
+
"DomainTemplate",
|
|
25
|
+
"FrameworkConfig",
|
|
26
|
+
"FrameworkTenantScope",
|
|
27
|
+
"HMSFactory",
|
|
28
|
+
"SessionManager",
|
|
29
|
+
"StreamChunk",
|
|
30
|
+
"SymfonicAgent",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def __getattr__(name: str) -> object:
|
|
35
|
+
"""Lazy-load public API symbols to avoid circular imports."""
|
|
36
|
+
if name in ("AgentRequest", "AgentResponse", "FrameworkTenantScope", "StreamChunk"):
|
|
37
|
+
from symfonic.agent import types
|
|
38
|
+
|
|
39
|
+
return getattr(types, name)
|
|
40
|
+
|
|
41
|
+
if name in ("DomainTemplate",):
|
|
42
|
+
from symfonic.agent import domain
|
|
43
|
+
|
|
44
|
+
return getattr(domain, name)
|
|
45
|
+
|
|
46
|
+
if name in ("FrameworkConfig",):
|
|
47
|
+
from symfonic.agent import config
|
|
48
|
+
|
|
49
|
+
return getattr(config, name)
|
|
50
|
+
|
|
51
|
+
if name in ("SymfonicAgent",):
|
|
52
|
+
from symfonic.agent import engine
|
|
53
|
+
|
|
54
|
+
return getattr(engine, name)
|
|
55
|
+
|
|
56
|
+
if name in ("HMSFactory",):
|
|
57
|
+
from symfonic.agent import factory
|
|
58
|
+
|
|
59
|
+
return getattr(factory, name)
|
|
60
|
+
|
|
61
|
+
if name in ("SessionManager",):
|
|
62
|
+
from symfonic.agent import sessions
|
|
63
|
+
|
|
64
|
+
return getattr(sessions, name)
|
|
65
|
+
|
|
66
|
+
raise AttributeError(f"module 'symfonic.agent' has no attribute {name!r}")
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Symfonic agent CLI package."""
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"""Symfonic agent CLI.
|
|
2
|
+
|
|
3
|
+
Commands:
|
|
4
|
+
chat -- Run a single query against the agent.
|
|
5
|
+
migrate -- Placeholder for future HMS data migration.
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
python -m symfonic.agent.cli.main chat "Hello" --tenant-id t1
|
|
9
|
+
symfonic chat "Hello" --tenant-id t1
|
|
10
|
+
symfonic migrate old://db new://db
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import asyncio
|
|
16
|
+
import sys
|
|
17
|
+
import time
|
|
18
|
+
|
|
19
|
+
try:
|
|
20
|
+
import typer
|
|
21
|
+
except ImportError as _err: # pragma: no cover
|
|
22
|
+
raise ImportError(
|
|
23
|
+
"typer is required for the CLI. "
|
|
24
|
+
"Install it with: pip install symfonic-core[cli]"
|
|
25
|
+
) from _err
|
|
26
|
+
|
|
27
|
+
from symfonic.agent.config import FrameworkConfig
|
|
28
|
+
from symfonic.agent.domain import DomainTemplate
|
|
29
|
+
from symfonic.agent.engine import SymfonicAgent
|
|
30
|
+
from symfonic.agent.types import AgentResponse, FrameworkTenantScope
|
|
31
|
+
from symfonic.core.testing import MockModelProvider
|
|
32
|
+
|
|
33
|
+
app = typer.Typer(
|
|
34
|
+
name="symfonic",
|
|
35
|
+
help="Symfonic agent command-line interface.",
|
|
36
|
+
add_completion=False,
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@app.command()
|
|
41
|
+
def chat(
|
|
42
|
+
query: str = typer.Argument(..., help="Query to send to the agent."),
|
|
43
|
+
tenant_id: str = typer.Option(..., "--tenant-id", help="Tenant identifier (required)."),
|
|
44
|
+
dsn: str | None = typer.Option(None, "--dsn", help="Postgres DSN for persistent memory."),
|
|
45
|
+
model: str = typer.Option("mock", "--model", help="Model provider name (default: mock)."),
|
|
46
|
+
enable_hms: bool = typer.Option(False, "--enable-hms", help="Enable HMS-aware system prompt."),
|
|
47
|
+
domain: str = typer.Option(
|
|
48
|
+
"default",
|
|
49
|
+
"--domain",
|
|
50
|
+
help="Domain template name. Use 'default' for generic agent. "
|
|
51
|
+
"Custom domains should be injected programmatically.",
|
|
52
|
+
),
|
|
53
|
+
) -> None:
|
|
54
|
+
"""Run a single query against the Symfonic agent."""
|
|
55
|
+
if dsn:
|
|
56
|
+
typer.echo(
|
|
57
|
+
"Warning: --dsn is not yet wired to Postgres backends. Using in-memory.",
|
|
58
|
+
err=True,
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
if model == "mock":
|
|
62
|
+
provider = MockModelProvider(response=f"[mock] Responding to: {query}")
|
|
63
|
+
elif model == "anthropic":
|
|
64
|
+
try:
|
|
65
|
+
from symfonic.core.providers import AnthropicProvider # pragma: no cover
|
|
66
|
+
provider = AnthropicProvider() # pragma: no cover
|
|
67
|
+
except ImportError as exc:
|
|
68
|
+
typer.echo(
|
|
69
|
+
"Anthropic provider requires: pip install symfonic-core[anthropic]",
|
|
70
|
+
err=True,
|
|
71
|
+
)
|
|
72
|
+
raise SystemExit(1) from exc
|
|
73
|
+
else:
|
|
74
|
+
typer.echo(f"Unknown model provider: {model}. Use 'mock' or 'anthropic'.", err=True)
|
|
75
|
+
raise SystemExit(1)
|
|
76
|
+
domain_template = DomainTemplate(name=domain)
|
|
77
|
+
config = FrameworkConfig(domain=domain_template)
|
|
78
|
+
agent = SymfonicAgent(
|
|
79
|
+
model_provider=provider, config=config, enable_hms_prompt=enable_hms,
|
|
80
|
+
)
|
|
81
|
+
scope = FrameworkTenantScope(tenant_id=tenant_id)
|
|
82
|
+
|
|
83
|
+
if enable_hms:
|
|
84
|
+
print("Thinking (HMS enabled)...", file=sys.stderr)
|
|
85
|
+
|
|
86
|
+
async def _run_and_flush() -> AgentResponse:
|
|
87
|
+
response = await agent.run(query, scope=scope)
|
|
88
|
+
await agent.flush_background_tasks()
|
|
89
|
+
return response
|
|
90
|
+
|
|
91
|
+
start = time.monotonic()
|
|
92
|
+
response = asyncio.run(_run_and_flush())
|
|
93
|
+
elapsed_ms = (time.monotonic() - start) * 1000
|
|
94
|
+
|
|
95
|
+
typer.echo(response.final_response or "(no response)")
|
|
96
|
+
in_tok = len(query) // 3
|
|
97
|
+
out_tok = len(response.final_response or "") // 3
|
|
98
|
+
sys_tok = response.system_prompt_tokens
|
|
99
|
+
total_tok = in_tok + sys_tok + out_tok
|
|
100
|
+
print(
|
|
101
|
+
f"tokens=~{total_tok} (in=~{in_tok} +system=~{sys_tok} out=~{out_tok}) "
|
|
102
|
+
f"memory={response.memory_entries_used} "
|
|
103
|
+
f"duration_ms={elapsed_ms:.1f}",
|
|
104
|
+
file=sys.stderr,
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
@app.command()
|
|
109
|
+
def migrate(
|
|
110
|
+
source_uri: str = typer.Argument(..., help="Source data URI."),
|
|
111
|
+
target_uri: str = typer.Argument(..., help="Target data URI."),
|
|
112
|
+
) -> None:
|
|
113
|
+
"""Migrate HMS data between storage backends (stub)."""
|
|
114
|
+
typer.echo(f"Migration from {source_uri} to {target_uri} is not yet implemented")
|
|
115
|
+
raise SystemExit(0)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
if __name__ == "__main__": # pragma: no cover
|
|
119
|
+
app()
|
symfonic/agent/config.py
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"""FrameworkConfig -- unified configuration for the symfonic agent framework.
|
|
2
|
+
|
|
3
|
+
Composes core AgentConfig and memory OrchestratorConfig with
|
|
4
|
+
framework-specific behaviour flags.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
from pydantic import BaseModel, Field
|
|
12
|
+
|
|
13
|
+
from symfonic.agent.domain import DEFAULT_DOMAIN, DomainTemplate
|
|
14
|
+
from symfonic.core.config import AgentConfig
|
|
15
|
+
from symfonic.infra.protocols import NullScheduler, TaskSchedulerProtocol
|
|
16
|
+
from symfonic.memory.orchestrator.config import OrchestratorConfig
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class FrameworkConfig(BaseModel, frozen=True):
|
|
20
|
+
"""Immutable configuration composing core and memory configs.
|
|
21
|
+
|
|
22
|
+
Framework-specific flags control automatic hydration, consolidation,
|
|
23
|
+
lazy tool routing, and streaming.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
agent: AgentConfig = Field(
|
|
27
|
+
default_factory=AgentConfig,
|
|
28
|
+
description="Core agent runtime configuration",
|
|
29
|
+
)
|
|
30
|
+
orchestrator: OrchestratorConfig = Field(
|
|
31
|
+
default_factory=OrchestratorConfig,
|
|
32
|
+
description="Memory orchestrator configuration",
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
# -- Framework behaviour flags -------------------------------------------
|
|
36
|
+
|
|
37
|
+
auto_hydrate: bool = Field(
|
|
38
|
+
default=True,
|
|
39
|
+
description="Automatically hydrate memory context before LLM execution",
|
|
40
|
+
)
|
|
41
|
+
auto_consolidate: bool = Field(
|
|
42
|
+
default=True,
|
|
43
|
+
description="Automatically extract and commit memories after execution",
|
|
44
|
+
)
|
|
45
|
+
lazy_tooling: bool = Field(
|
|
46
|
+
default=True,
|
|
47
|
+
description="Dynamically filter tools via CapabilityRouter per query",
|
|
48
|
+
)
|
|
49
|
+
streaming_enabled: bool = Field(
|
|
50
|
+
default=True,
|
|
51
|
+
description="Enable the stream() interface on SymfonicAgent",
|
|
52
|
+
)
|
|
53
|
+
enabled_layers: set[str] = Field(
|
|
54
|
+
default_factory=lambda: {
|
|
55
|
+
"working", "episodic", "semantic", "procedural", "prospective",
|
|
56
|
+
},
|
|
57
|
+
description="Set of memory layer names to hydrate during auto_hydrate",
|
|
58
|
+
)
|
|
59
|
+
domain: DomainTemplate = Field(
|
|
60
|
+
default_factory=lambda: DEFAULT_DOMAIN,
|
|
61
|
+
description="Pluggable domain template for business-specific behavior",
|
|
62
|
+
)
|
|
63
|
+
scheduler: Any = Field(
|
|
64
|
+
default=None,
|
|
65
|
+
description=(
|
|
66
|
+
"Optional TaskSchedulerProtocol implementation for background "
|
|
67
|
+
"task scheduling. None uses NullScheduler (no-op)."
|
|
68
|
+
),
|
|
69
|
+
)
|
|
70
|
+
spreading_activation: bool = Field(
|
|
71
|
+
default=True,
|
|
72
|
+
description=(
|
|
73
|
+
"Enable spreading activation: auto-fetch 1st-degree neighbor "
|
|
74
|
+
"nodes when semantic retrieval produces hits."
|
|
75
|
+
),
|
|
76
|
+
)
|
|
77
|
+
self_reflection: bool = Field(
|
|
78
|
+
default=False,
|
|
79
|
+
description=(
|
|
80
|
+
"Enable post-interaction self-reflection to extract business "
|
|
81
|
+
"insights from the conversation and commit them to semantic memory."
|
|
82
|
+
),
|
|
83
|
+
)
|
|
84
|
+
reflection_prompt: str | None = Field(
|
|
85
|
+
default=None,
|
|
86
|
+
description=(
|
|
87
|
+
"Custom prompt template for the InsightExtractor. "
|
|
88
|
+
"Overrides the default general-purpose extraction prompt. "
|
|
89
|
+
"Must contain a {conversation} placeholder."
|
|
90
|
+
),
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
@property
|
|
94
|
+
def task_scheduler(self) -> TaskSchedulerProtocol:
|
|
95
|
+
"""Return the configured scheduler or a NullScheduler fallback."""
|
|
96
|
+
if self.scheduler is not None:
|
|
97
|
+
return self.scheduler
|
|
98
|
+
return NullScheduler()
|
|
99
|
+
|
|
100
|
+
@classmethod
|
|
101
|
+
def with_defaults(cls) -> FrameworkConfig:
|
|
102
|
+
"""Create a config with all default values."""
|
|
103
|
+
return cls()
|
symfonic/agent/domain.py
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"""DomainTemplate -- pluggable domain configuration for business-specific behavior.
|
|
2
|
+
|
|
3
|
+
External apps inject their own domain logic by creating a DomainTemplate
|
|
4
|
+
and passing it to FrameworkConfig. The framework stays generic; all
|
|
5
|
+
business-specific labels, onboarding flows, and schema definitions live
|
|
6
|
+
in the consuming application.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
from pydantic import BaseModel, Field
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class MonitoringBlueprint(BaseModel, frozen=True):
|
|
17
|
+
"""Configuration for sub-agent monitoring and anomaly detection.
|
|
18
|
+
|
|
19
|
+
Defines thresholds, check intervals, and which metrics trigger
|
|
20
|
+
alerts. Consumed by monitoring skills (e.g. AnomalyDetectionSkill)
|
|
21
|
+
in the application layer.
|
|
22
|
+
|
|
23
|
+
Attributes:
|
|
24
|
+
anomaly_thresholds: Metric name to deviation percentage threshold.
|
|
25
|
+
When a metric deviates beyond this percentage, it triggers
|
|
26
|
+
an alert. Example: ``{"sales": 20.0, "inventory": 30.0}``.
|
|
27
|
+
check_interval_seconds: How often automated checks should run.
|
|
28
|
+
alert_on: List of metric names to monitor. Only metrics listed
|
|
29
|
+
here produce findings.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
anomaly_thresholds: dict[str, float] = Field(default_factory=dict)
|
|
33
|
+
check_interval_seconds: int = 300
|
|
34
|
+
alert_on: list[str] = Field(default_factory=list)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class DomainTemplate(BaseModel, frozen=True):
|
|
38
|
+
"""Pluggable domain configuration for business-specific behavior.
|
|
39
|
+
|
|
40
|
+
External apps inject their own domain logic by creating a DomainTemplate
|
|
41
|
+
and passing it to FrameworkConfig. The framework stays generic.
|
|
42
|
+
|
|
43
|
+
Attributes:
|
|
44
|
+
name: Human-readable domain identifier (e.g. "amazon-expert").
|
|
45
|
+
required_labels: Graph labels the domain expects to exist.
|
|
46
|
+
Used by DiscoveryService to flag missing blocks as pending.
|
|
47
|
+
onboarding_checklist: Items the agent should collect during
|
|
48
|
+
initial conversations with a new tenant.
|
|
49
|
+
soul_schema: Schema definition for the SOUL label -- maps
|
|
50
|
+
field names to their expected types as strings.
|
|
51
|
+
description: Optional description of the domain's purpose.
|
|
52
|
+
tool_manifest: Short descriptions of available tools. Each entry
|
|
53
|
+
is ``"tool_name: short description"``. Injected into the
|
|
54
|
+
system prompt so the LLM knows which tools exist without
|
|
55
|
+
loading full schemas upfront.
|
|
56
|
+
tool_catalog: Full JSON schemas keyed by tool name. Used for
|
|
57
|
+
JIT hydration -- the engine loads the full schema only when
|
|
58
|
+
the LLM selects a tool from the manifest.
|
|
59
|
+
monitoring: Blueprint for sub-agent monitoring and anomaly
|
|
60
|
+
detection. Provides thresholds, intervals, and alert
|
|
61
|
+
configuration.
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
name: str = "default"
|
|
65
|
+
required_labels: list[str] = Field(default_factory=list)
|
|
66
|
+
onboarding_checklist: list[str] = Field(default_factory=list)
|
|
67
|
+
soul_schema: dict[str, str] = Field(default_factory=dict)
|
|
68
|
+
description: str = ""
|
|
69
|
+
tool_manifest: list[str] = Field(default_factory=list)
|
|
70
|
+
tool_catalog: dict[str, dict[str, Any]] = Field(default_factory=dict)
|
|
71
|
+
monitoring: MonitoringBlueprint = Field(default_factory=MonitoringBlueprint)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
DEFAULT_DOMAIN = DomainTemplate()
|