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

> ## Agent Instructions
> To search or read these docs, connect the Ringg docs MCP server at https://docs.ringg.ai/mcp (no key needed; tools search_ringg_ai and query_docs_filesystem_ringg_ai) instead of browsing pages one by one. Setup for each client: https://docs.ringg.ai/resources/mcp-server/docs-mcp-server/mcp-for-ai-assistants.md
> The dashboard labels agents "Assistants"; these docs say "agent". Both mean the same object, identified by agent_id.
> API base URL: https://prod-api.ringg.ai/ca/api/v0. Send the workspace API key in the X-API-KEY header, from server-side code only.
> Placing a call dials a real phone number and spends credits. Confirm the number with the user before calling.
> To act on a Ringg workspace (place calls, edit agents, read transcripts), use the separate Ringg workspace MCP server at https://mcp.ringg.ai/mcp: https://docs.ringg.ai/resources/mcp-server/workspace-mcp-server/overview.md

# Lesson: Logs

> Open the dry-run campaign's calls in Logs, read one call's transcript and Pre-Call tool log, check Advanced analysis, and filter by payment_promised.

export const Quiz = ({question, answers, correctFeedback, incorrectFeedback}) => {
  const [selected, setSelected] = React.useState(null);
  const [checked, setChecked] = React.useState(false);
  const quizId = React.useId();
  const isCorrect = checked && answers[selected]?.correct;
  const reset = () => {
    setSelected(null);
    setChecked(false);
  };
  const optionStyle = (answer, i) => {
    const base = {
      display: "flex",
      alignItems: "flex-start",
      gap: "0.6rem",
      padding: "0.6rem 0.8rem",
      marginTop: "0.5rem",
      borderRadius: "0.6rem",
      border: "1px solid rgba(128, 128, 128, 0.35)",
      cursor: checked ? "default" : "pointer",
      lineHeight: 1.45
    };
    if (checked && answer.correct) {
      return {
        ...base,
        borderColor: "rgba(22, 163, 74, 0.8)",
        background: "rgba(22, 163, 74, 0.12)"
      };
    }
    if (checked && selected === i && !answer.correct) {
      return {
        ...base,
        borderColor: "rgba(220, 38, 38, 0.8)",
        background: "rgba(220, 38, 38, 0.1)"
      };
    }
    if (!checked && selected === i) {
      return {
        ...base,
        borderColor: "currentColor",
        background: "rgba(128, 128, 128, 0.12)"
      };
    }
    return base;
  };
  const buttonStyle = disabled => ({
    marginTop: "0.9rem",
    padding: "0.45rem 0.9rem",
    borderRadius: "0.5rem",
    border: "1px solid rgba(128, 128, 128, 0.5)",
    background: "rgba(128, 128, 128, 0.1)",
    color: "inherit",
    font: "inherit",
    fontSize: "0.9em",
    cursor: disabled ? "not-allowed" : "pointer",
    opacity: disabled ? 0.5 : 1
  });
  return <div style={{
    marginTop: "1.5rem",
    padding: "1rem 1.1rem",
    borderRadius: "0.8rem",
    border: "1px solid rgba(128, 128, 128, 0.35)"
  }}>
      <Badge color="green">Quiz</Badge>
      <p id={quizId + "-question"} style={{
    fontWeight: 600,
    margin: "0.6rem 0 0.2rem"
  }}>
        {question}
      </p>
      <div role="radiogroup" aria-labelledby={quizId + "-question"} aria-disabled={checked}>
        {answers.map((answer, i) => <label key={i} style={optionStyle(answer, i)}>
            <input type="radio" name={"quiz-" + quizId} checked={selected === i} onChange={() => !checked && setSelected(i)} disabled={checked} style={{
    marginTop: "0.3rem",
    flexShrink: 0
  }} />
            <span>{answer.text}</span>
          </label>)}
      </div>
      {checked && <div role="status" aria-live="polite" aria-atomic="true" style={{
    marginTop: "0.9rem",
    padding: "0.7rem 0.9rem",
    borderRadius: "0.6rem",
    lineHeight: 1.5,
    background: isCorrect ? "rgba(22, 163, 74, 0.12)" : "rgba(220, 38, 38, 0.1)"
  }}>
          <strong style={{
    marginRight: "0.4rem"
  }}>{isCorrect ? "✓" : "✗"}</strong>
          {isCorrect ? correctFeedback : incorrectFeedback}
        </div>}
      {!checked ? <button type="button" onClick={() => selected !== null && setChecked(true)} disabled={selected === null} style={buttonStyle(selected === null)}>
          Check answer
        </button> : <button type="button" onClick={reset} style={buttonStyle(false)}>
          Try again
        </button>}
    </div>;
};

export const RelatedTopics = ({items}) => <div className="not-prose mt-12">
    <div className="text-sm font-medium text-gray-500 dark:text-zinc-400 mb-3">Related topics</div>
    <div className="flex flex-col gap-2.5">
      {items.map(([title, href]) => <a key={href} href={href} className="flex items-center gap-2.5 text-sm text-gray-700 hover:text-gray-950 dark:text-zinc-300 dark:hover:text-white">
          <Icon icon="file-text" size={16} color="currentColor" />
          {title}
        </a>)}
    </div>
  </div>;

**Part 6: Measuring and improving your agent · Lesson 1 of 4 · 15 minutes**

## Objective

Find every call of the dry-run campaign and read one of them down to its transcript, tool log and analysis.

## The scenario

The dry run from part 4 placed three calls. Acme's collections lead wants to know which customers promised to pay, whether the CRM lookup ran before each call, and what Ananya said when someone objected. All of it is in Logs.

## Hands-on

<Frame caption="Filtering Logs, opening a call and exporting">
  <video alt="Filtering Logs, opening a call and exporting" aria-label="Filtering Logs, opening a call and exporting" controls muted playsInline className="w-full rounded-xl" style={{ aspectRatio: "16 / 10" }} preload="metadata" controlsList="nodownload noremoteplayback" poster="/media/monitor-logs/poster.webp">
    <source src="https://mintcdn.com/ringgai-0da73d20/XUOcNie5hfK3q--Y/media/monitor-logs/video.webm?fit=max&auto=format&n=XUOcNie5hfK3q--Y&q=85&s=3ddfbdcaecd0ec7e27b93c05a4f979d9" type="video/webm; codecs=&#x22;av01.0.09M.08&#x22;" data-path="media/monitor-logs/video.webm" />
  </video>
</Frame>

<Steps>
  <Step title="Open the campaign's calls">
    On **Monitor → Campaigns**, click **EMI reminders - dry run** and then **History**. Logs opens filtered to the campaign, with every call whatever its date. From Logs itself, the same view is **Filters → Campaigns**.
  </Step>

  <Step title="Read the list">
    Each row shows the **Assistant** (with a version chip, since Ananya has V1 and V2), the **Callee** with their name beneath, **Called on**, **Status**, **Duration** and **Cost**. A call that went to a second attempt has a chevron, **Expand attempts**, which shows each attempt as its own row.
  </Step>

  <Step title="Open a call">
    Click the row of the call you answered. The header shows the call ID with a copy button, the status, **From**, **Cost** and **Origin** **Campaign**. Play the recording, or **Download recording**. The **Call details** tab lists **Call latency**, **Call duration**, the **Custom variables** the CSV filled (`due_amount`, `due_date`, `loan_account`), then the general analysis. Right after a call it reads "General analysis is currently under process!" for a short while.
  </Step>

  <Step title="Read the transcript and the tool log">
    Open **Transcript**. The turns run top to bottom, with the tools that ran grouped under **Pre-Call**, **On-Call** and **Post-Call**. Click `crm_lookup` under **Pre-Call**: its log shows the HTTP status, latency, when it ran, and **Request** and **Response** tabs (or **Error**). The copy icon copies the whole log as JSON, which is what you send a backend colleague when the lookup fails.
  </Step>

  <Step title="Check the analysis fields">
    Open **Advanced analysis**. It holds the values Ananya extracted in part 3: `payment_promised`, `promised_date` and `objection`. The tab appears only when there is something to show.
  </Step>

  <Step title="Filter by what was said">
    Click **Filters**. Under **Assistants** tick **EMI reminder - Hindi** and nothing else; **Advanced analysis** needs exactly one assistant. Add the condition `payment_promised` **is** true and apply.
  </Step>
</Steps>

## Checkpoint

<Check>
  The list narrows to the calls where the person said they would pay, and the filters show as chips next to **Filters**. **Reset** clears them.
</Check>

## Exercise

Export what you filtered: click **Export** in the table footer and choose **Export with analysis**. Expected result: nothing downloads; a message says "Call history report (with the applied filters) is being sent to your email." The report arrives by email and uses the filters that were on screen.

## What you learned

* **History** on a campaign opens Logs for its calls with no date limit. **Call ID**, **From number**, **To number** and **Campaigns** also ignore the date range, which otherwise defaults to the last month.
* The call panel holds the recording, **Call details** (latency, duration, variables, general analysis), **Advanced analysis**, the **Transcript** with each tool's request and response, and **Evals** once a call is scored.
* The **Custom variables** and **Advanced analysis** filters work with exactly one assistant selected.

<Quiz
  question="You want every call from the dry-run campaign, including the two placed last month. Which is the fastest way, and will the date range hide any of them?"
  answers={[
{ text: "Filters → Call status: Completed; the date range hides older calls", correct: false },
{ text: "History on the campaign; the Campaigns filter ignores the date range", correct: true },
{ text: "Search by callee name; the date range applies", correct: false },
{ text: "Export in the table footer; it covers all dates", correct: false },
]}
  correctFeedback="Right. History on a campaign opens Logs filtered to it with no date limit; the Campaigns, Call ID, From number and To number filters all ignore the date range, which otherwise defaults to the last month."
  incorrectFeedback="Not quite. The Campaigns filter, like Call ID, From number and To number, ignores the date range, so History on the campaign shows every call whatever its date. Other filters and Export use the date range on screen."
/>

<RelatedTopics items={[["Logs", "/documentation/monitor/logs"], ["Manage a campaign", "/documentation/deploy/campaigns/manage-a-campaign"]]} />


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.