> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cekura.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Build a Metric with AI

> Refine an LLM Judge or Python metric with an AI agent that runs it on your real calls and runs, fixes clear edge cases itself, and asks you only when a decision is genuinely ambiguous

export const CopyPageButton = () => {
  if (typeof window !== 'undefined') {
    setTimeout(function () {
      if (document.getElementById('ck-tools')) return;
      var anchor = document.getElementById('content-area') || document.querySelector('.mdx-content');
      if (!anchor) return;
      if (!document.getElementById('ck-style')) {
        var s = document.createElement('style');
        s.id = 'ck-style';
        s.textContent = '#ck-tools{position:absolute;top:6px;right:0;z-index:100;font-family:inherit;}' + '.ck-row{display:inline-flex;align-items:stretch;border:1px solid rgba(0,0,0,0.15);border-radius:8px;overflow:hidden;background:#fff;}' + ':root.dark .ck-row{background:rgba(255,255,255,0.06);border-color:rgba(255,255,255,0.12);}' + '.ck-btn{padding:5px 12px;border:none;background:none;cursor:pointer;font-size:13px;font-weight:500;font-family:inherit;color:#374151;}' + ':root.dark .ck-btn{color:#d1d5db;}' + '.ck-btn:hover{background:rgba(0,0,0,0.04);}' + ':root.dark .ck-btn:hover{background:rgba(255,255,255,0.06);}' + '.ck-chevron{padding:5px 8px;border:none;background:none;cursor:pointer;font-size:14px;font-family:inherit;color:#374151;}' + ':root.dark .ck-chevron{color:#d1d5db;}' + '.ck-chevron:hover{background:rgba(0,0,0,0.04);}' + ':root.dark .ck-chevron:hover{background:rgba(255,255,255,0.06);}' + '.ck-divider{width:1px;background:rgba(0,0,0,0.12);flex-shrink:0;}' + ':root.dark .ck-divider{background:rgba(255,255,255,0.12);}' + '.ck-dd{position:absolute;top:calc(100% + 4px);right:0;min-width:180px;background:#fff;border:1px solid rgba(0,0,0,0.12);border-radius:8px;box-shadow:0 4px 12px rgba(0,0,0,0.1);padding:4px;display:none;z-index:200;}' + ':root.dark .ck-dd{background:#1f2937;border-color:rgba(255,255,255,0.1);box-shadow:0 4px 16px rgba(0,0,0,0.35);}' + '.ck-item{display:block;width:100%;padding:7px 12px;border:none;background:none;border-radius:6px;cursor:pointer;font-size:13px;font-family:inherit;text-align:left;color:#374151;}' + ':root.dark .ck-item{color:#d1d5db;}' + '.ck-item:hover{background:rgba(0,0,0,0.05);}' + ':root.dark .ck-item:hover{background:rgba(255,255,255,0.07);}';
        document.head.appendChild(s);
      }
      var wrap = document.createElement('div');
      wrap.id = 'ck-tools';
      var row = document.createElement('div');
      row.className = 'ck-row';
      var mainBtn = document.createElement('button');
      mainBtn.className = 'ck-btn';
      mainBtn.textContent = 'Copy page';
      var divider = document.createElement('span');
      divider.className = 'ck-divider';
      var chevron = document.createElement('button');
      chevron.className = 'ck-chevron';
      chevron.textContent = '▾';
      var dd = document.createElement('div');
      dd.className = 'ck-dd';
      function closeDD() {
        dd.style.display = 'none';
      }
      function openDD() {
        dd.style.display = 'block';
      }
      chevron.onclick = function (e) {
        e.stopPropagation();
        if (dd.style.display === 'block') {
          closeDD();
        } else {
          openDD();
        }
      };
      document.addEventListener('click', function (e) {
        if (!e.target.closest('#ck-tools')) {
          closeDD();
        }
      });
      document.addEventListener('keydown', function (e) {
        if (e.key === 'Escape') {
          closeDD();
        }
      });
      function makeItem(label, fn) {
        var b = document.createElement('button');
        b.className = 'ck-item';
        b.textContent = label;
        b.onclick = function () {
          fn();
          closeDD();
        };
        return b;
      }
      function getMarkdown() {
        var walk = function (node) {
          if (!node) return '';
          if (node.nodeType === 3) return node.textContent || '';
          if (node.nodeType !== 1) return '';
          var tag = node.tagName.toLowerCase();
          var skip = ['script', 'style', 'svg', 'noscript', 'button', 'iframe'];
          if (skip.indexOf(tag) !== -1) return '';
          if (node.id === 'ck-tools') return '';
          var ch = Array.from(node.childNodes).map(walk).join('');
          if (tag === 'h1') return '\n# ' + ch.trim() + '\n\n';
          if (tag === 'h2') return '\n## ' + ch.trim() + '\n\n';
          if (tag === 'h3') return '\n### ' + ch.trim() + '\n\n';
          if (tag === 'p') return '\n' + ch.trim() + '\n\n';
          if (tag === 'pre') return '\n```\n' + node.textContent.trim() + '\n```\n\n';
          if (tag === 'li') return '- ' + ch.trim() + '\n';
          if (tag === 'code') return '`' + ch.trim() + '`';
          return ch;
        };
        var content = document.querySelector('.mdx-content') || document.getElementById('content-area') || document.body;
        return walk(content).replace(/\n\n\n+/g, '\n\n').trim();
      }
      function copyMd() {
        var md = getMarkdown();
        navigator.clipboard.writeText(md).then(function () {
          mainBtn.textContent = 'Copied!';
          setTimeout(function () {
            mainBtn.textContent = 'Copy page';
          }, 2000);
        });
      }
      function viewMd() {
        var md = getMarkdown();
        var safe = md.split('&').join('&amp;').split('<').join('&lt;').split('>').join('&gt;');
        var html = '<!DOCTYPE html><html><head><meta charset="utf-8"><style>body{font-family:monospace;max-width:860px;margin:40px auto;padding:0 24px;line-height:1.7;white-space:pre-wrap;word-wrap:break-word}</style></head><body>' + safe + '</body></html>';
        window.open(URL.createObjectURL(new Blob([html], {
          type: 'text/html'
        })), '_blank');
      }
      function openClaude() {
        var prompt = 'Can you read this Cekura docs page ' + window.location.href + ' so I can ask you questions?';
        window.open('https://claude.ai/new?q=' + encodeURIComponent(prompt), '_blank');
      }
      mainBtn.onclick = copyMd;
      dd.appendChild(makeItem('Copy page', copyMd));
      dd.appendChild(makeItem('View as Markdown', viewMd));
      dd.appendChild(makeItem('Open in Claude', openClaude));
      row.appendChild(mainBtn);
      row.appendChild(divider);
      row.appendChild(chevron);
      wrap.appendChild(row);
      wrap.appendChild(dd);
      anchor.style.position = 'relative';
      anchor.insertBefore(wrap, anchor.firstChild);
    }, 50);
  }
  return null;
};

<CopyPageButton />

Writing a metric that behaves exactly the way you intend usually takes a few
rounds of trial and error — write a definition, preview it on some calls,
notice a case it gets wrong, tighten the wording, repeat. **Build with AI**
collapses that loop into a single conversation.

When you click **Improve** on a metric's definition, an AI agent:

1. Cleans up your definition and gives it a quick check. If the intent is
   unclear or the definition has an obvious gap, it asks you a short question
   **up front** — before spending a run on calls it can't yet judge meaningfully.
2. Runs the definition against a sample of the agent's real **calls and runs**.
3. Reviews the predictions and finds edge cases — early hang-ups, partial
   completions, off-topic calls, caller-vs-agent fault, voicemail, transfers,
   and so on.
4. **Resolves the clear cases itself** by tightening the definition, and asks
   you a short question only when a verdict depends on a policy it cannot infer
   (for example, "should a partial completion count as PASS?").
5. Proposes a refined definition for you to review and apply.

<Note>
  Build with AI works for both **LLM Judge** metrics (it refines the natural-language
  description) and **Python** metrics (it makes surgical edits to your code — see
  below). You commit the final metric yourself; nothing is saved until you click
  **Use this metric** and then **Create**/**Update**.
</Note>

### Starting a build

<Steps>
  <Step title="Write a starting point">
    For an **LLM Judge** metric, write a first-pass description of what success
    looks like. For a **Python** metric, write your initial evaluation code.
    You don't need to get it perfect — that's what the builder is for.
  </Step>

  <Step title="Click Improve">
    The **Improve** button sits next to the Description (LLM Judge) or the Custom
    Code editor (Python). Pick the agent whose calls and runs the builder should
    sample from.
  </Step>

  <Step title="Chat with the builder">
    The builder works through your calls and runs and either asks a clarifying
    question or presents a refined definition. Answer questions by selecting an
    option (the recommended default is marked) or typing your own guidance. You
    can also message the builder at any time — for example, "make it stricter
    about confirming the appointment time."
  </Step>

  <Step title="Review and apply">
    When it's done, the builder shows a diff of the proposed definition against
    your original, plus a short list of the edge cases it handled. Click
    **Use this metric** to drop the refined definition into the form, then save.
  </Step>
</Steps>

### Working in the background

A build runs an AI agent over dozens of real calls and runs, so it typically
takes **a few minutes** (usually 4–6). You don't have to wait on it:

* **Minimize** the chat and it keeps running as a small card in the corner.
* The card **follows you across the platform** — open another metric, inspect
  the example calls the builder linked, or check a run, and the build keeps
  going.
* Reopen the card any time to see progress, answer a question, or apply the
  result.

The card shows the current step and elapsed time so you always know where the
build is.

### Python metrics

For a Python metric the builder works in **code**. Before it runs anything, it
cleans up your starting point — fixing syntax errors and obvious bugs — so a
rough first draft doesn't stall the build. From there it runs your code on the
sampled calls and runs and makes the smallest change that fixes each case it
gets wrong, keeping it valid, runnable Python in the same style as what you
wrote.

<Tip>
  You don't have to start from code. Describe the metric in **plain English** in
  the Python editor and the builder turns it into a working Python metric on the
  first pass — then refines it against your real calls and runs like any other
  build.
</Tip>

Everything the builder produces is the exact code the metric will run in
production, so what you review is what you ship.

### Credits

A build runs your metric against the sampled calls and runs, and consumes credits
for each pass, priced the same way the metric optimizer is:

* **LLM Judge metrics** — and Python metrics that call `evaluate_llm_judge_metric`
  — are charged at the **LLM-judge** per-evaluation rate.
* **Python metrics that judge audio** (calling `evaluate_llm_judge_metric` with
  `audio=True`) are charged at the **audio** per-minute rate times each call's
  duration. A time window (`audio_start_time`/`audio_end_time`) changes what the
  judge listens to, not the charge.
* **Pure Python metrics** are charged at the **custom-code** per-evaluation rate.

The cost of a pass is roughly the number of sampled items (≈50) times that rate.
A pass runs only when the metric definition actually changed, so answering a
clarifying question or sending a note that doesn't alter the metric won't
re-charge. Minimizing the chat doesn't stop the build; if you don't want to spend
more credits, **Stop** it.

## Related Documentation

* [LLM Judge Metric](/documentation/key-concepts/metrics/llm-judge-metric) - Evaluate calls with natural-language criteria
* [Python Metric](/documentation/key-concepts/metrics/python-metric) - Write custom evaluation logic in Python
* [Creating Good Metrics](/documentation/guides/creating-good-metric) - A complete guide to building high-fidelity metrics
* [Metric Variables](/documentation/key-concepts/metrics/metric-variables) - Variables you can use in metric definitions
