Back to course overview
Module 5From question to metric: the agent interface 13 min

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.

pythonpython
{
  "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.

agent/tools.py (excerpt)python
{
  "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"],
  },
}
Good tool descriptions are prompt engineering

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.

Note

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.