Tools: the agent's interface to the layer
Design the two tools that expose the semantic layer to Claude — a catalog and a query — with schemas the model can use reliably.
Claude interacts with the world through tools — functions you describe with a name, a description, and a JSON schema for inputs. The model decides when to call them and with what arguments; your code runs them. For our agent, two tools are enough.
Tool 1 — list_metrics (the catalog)
So the model knows what it can ask for, expose the catalog: every metric and dimension with a label and description. The model calls this when it's unsure of a name.
{
"name": "list_metrics",
"description": "List every metric and dimension the semantic layer can answer, "
"with labels and descriptions. Call this if unsure of a name.",
"input_schema": {"type": "object", "properties": {}, "additionalProperties": False},
}Tool 2 — query_metrics (the workhorse)
This maps one-to-one onto the semantic layer's query(): metric names, dimension names, optional time grain, filters, ordering, and limit. The description teaches the model how to use it well — with examples and the hard rule that it must not invent names.
{
"name": "query_metrics",
"description": "Query governed metrics. Choose metric and dimension NAMES from the "
"catalog; the semantic layer compiles the SQL. Never invent names. "
"e.g. revenue by product_category; aov by channel; revenue with "
"time_grain=month; cac by channel.",
"input_schema": {
"type": "object",
"properties": {
"metrics": {"type": "array", "items": {"type": "string"}},
"dimensions": {"type": "array", "items": {"type": "string"}},
"time_grain": {"type": "string", "enum": ["day","week","month","quarter","year"]},
"filters": {"type": "array", "items": {"type": "object", ...}},
"order_by": {"type": "string"},
"limit": {"type": "integer"},
},
"required": ["metrics"],
},
}The model relies on the description to decide when and how to call a tool. Being prescriptive — "choose names from the catalog," "never invent names," plus concrete examples — measurably improves how reliably it uses the tool. Vague descriptions produce vague behavior.
Notice the tools return structured JSON and accept structured input. The model handles the fuzzy human side; the tool boundary is crisp and typed. That boundary is what keeps the system reliable.