sofhiaazzhr's picture
fix(tools): align analyze_descriptive required args + normalize Timestamp in aggregate
4bb7623
Raw
History Blame
5.76 kB
"""Analytics tool registry
The real registry of the `analyze_*` family, built on the canonical `ToolSpec`
(src/tools/contracts.py) and the prompt-style `DESCRIPTION` constants the Planner
reads to choose a tool (KM-625). This replaces the agent team's local stub in
`src/agents/planner/registry.py` for the analytics slice.
Conventions (decided with the agent team, KM-465):
- **Pattern A** — `analyze_*` tools do NOT self-fetch by `source_id`. Each takes a
`data` argument that is a `"${t<id>}"` placeholder pointing at an upstream
`query_structured` table output, resolved to a DataFrame at execution time.
Column arguments reference the aliases that upstream query produced.
- `input_schema` is the lightweight JSON-schema-ish dict the planner validator
consumes: `required` (arg names with no default) + `properties` (allowed args).
`required` mirrors each compute function's no-default parameters; value-typing of
placeholder args is deferred to execution time.
- `output_kind` is the `ToolOutput.kind` each tool returns: stats (labelled-metric
dict) | table (rows×cols) | series (ordered periods).
The four data-access tools (query_structured / retrieve_documents / list_sources /
describe_source) are registered separately once their wrappers land (KM-465 #4);
`default_registry()` composes both slices.
"""
from __future__ import annotations
from src.tools.analytics import (
aggregation,
comparison,
decomposition,
descriptive,
quality,
relationship,
segmentation,
temporal,
)
from src.tools.contracts import ToolRegistry, ToolSpec
ANALYTICS_TOOLS: list[ToolSpec] = [
ToolSpec(
name="analyze_descriptive",
category="analytics.descriptive",
input_schema={
"required": ["data", "column_ids"],
"properties": {
"data": {"type": "string"},
"column_ids": {"type": "array"},
"metrics": {"type": "array"},
},
},
output_kind="stats",
description=descriptive.DESCRIPTION,
),
ToolSpec(
name="analyze_aggregate",
category="analytics.aggregation",
input_schema={
"required": ["data", "aggregations"],
"properties": {
"data": {"type": "string"},
"aggregations": {"type": "object"},
"group_by": {"type": "array"},
},
},
output_kind="table",
description=aggregation.DESCRIPTION,
),
ToolSpec(
name="analyze_comparison",
category="analytics.comparison",
input_schema={
"required": ["data", "dimension", "value_column", "group_a", "group_b"],
"properties": {
"data": {"type": "string"},
"dimension": {"type": "string"},
"value_column": {"type": "string"},
"group_a": {},
"group_b": {},
"agg": {"type": "string"},
},
},
output_kind="stats",
description=comparison.DESCRIPTION,
),
ToolSpec(
name="analyze_contribution",
category="analytics.decomposition",
input_schema={
"required": ["data", "dimension", "value_column"],
"properties": {
"data": {"type": "string"},
"dimension": {"type": "string"},
"value_column": {"type": "string"},
"agg": {"type": "string"},
"top_n": {"type": "integer"},
},
},
output_kind="table",
description=decomposition.DESCRIPTION,
),
ToolSpec(
name="analyze_profile",
category="analytics.quality",
input_schema={
"required": ["data"],
"properties": {
"data": {"type": "string"},
"column_ids": {"type": "array"},
},
},
output_kind="stats",
description=quality.DESCRIPTION,
),
ToolSpec(
name="analyze_correlation",
category="analytics.relationship",
input_schema={
"required": ["data"],
"properties": {
"data": {"type": "string"},
"column_ids": {"type": "array"},
"method": {"type": "string"},
},
},
output_kind="stats",
description=relationship.DESCRIPTION,
),
ToolSpec(
name="analyze_segment",
category="analytics.segmentation",
input_schema={
"required": ["data", "column", "bins"],
"properties": {
"data": {"type": "string"},
"column": {"type": "string"},
"bins": {},
"method": {"type": "string"},
"labels": {"type": "array"},
"value_column": {"type": "string"},
"agg": {"type": "string"},
},
},
output_kind="table",
description=segmentation.DESCRIPTION,
),
ToolSpec(
name="analyze_trend",
category="analytics.timeseries",
input_schema={
"required": ["data", "date_column", "value_column"],
"properties": {
"data": {"type": "string"},
"date_column": {"type": "string"},
"value_column": {"type": "string"},
"freq": {"type": "string"},
"agg": {"type": "string"},
},
},
output_kind="series",
description=temporal.DESCRIPTION,
),
]
def analytics_registry() -> ToolRegistry:
"""The analytics (`analyze_*`) slice of the tool registry (fresh instance)."""
return ToolRegistry(tools=list(ANALYTICS_TOOLS))