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

# HALO Desktop: Optimize an Agent End to End on Your Machine

> Run the full trace, analyze, fix loop entirely on your own machine with the free HALO desktop app. Load demo traces from Hugging Face, explore them in a local timeline, run HALO with your own model provider, and hand the report to Claude Code, Cursor, or Codex. No account, no cloud.

The [Try HALO with a Demo Repo](/guides/try-halo-demo-repo) guide runs this same loop against the hosted [Catalyst](/integrations/traces/quickstart) dashboard. This one does the whole thing **on your machine** with the free, open-source [HALO desktop app](https://github.com/context-labs/halo). Traces live in a local SQLite database, HALO runs against a model provider you configure, and nothing leaves your laptop. No Inference account required.

You will install the app, load a bundled demo dataset of about 1,000 real agent runs with one click, explore the traces in the local viewer, run HALO over them, and open the resulting report directly in a coding agent to apply the fixes. The traces come from a search agent with deliberate, documented flaws, so HALO has something real to find.

<Note>
  **Desktop or hosted?** The desktop app is the best way to try HALO end to end for free and keep your traces fully local. For continuous production observability across a team (always-on ingest, multiple users, scheduled HALO runs, Signals, and alerts), the [hosted version](/guides/try-halo-demo-repo) is the better fit. You can start local and move to hosted later without changing your instrumentation; it is the same Catalyst tracing under the hood. See [Self-hosting and production](#self-hosting-and-production).
</Note>

## Before you start

You need:

* The **HALO desktop app** (installed in [Step 1](#step-1-install-the-desktop-app)). HALO v1 ships for **Apple Silicon Macs** and **Ubuntu/Debian Linux (x64)**. Intel Macs, other Linux distributions, and Windows are not supported yet.
* A **model provider key** for running HALO. The desktop app supports OpenAI-compatible and Anthropic-compatible endpoints (OpenAI, Anthropic, OpenRouter, [Inference](https://inference.net), or your own endpoint), and you bring your own key. The app stores it locally and it never leaves your machine.
* A **coding agent** for the last step: Claude Code, Cursor, or Codex. The report opens in any of them with one click, and there is a copy-paste path for everything else.

<Note>
  **What "no account" means.** The desktop app, the local trace timeline, and the HALO engine all run with no Inference account and no sign-in. The one thing that always needs a key is a model provider, because HALO calls an LLM to do the analysis. That key can be any provider you already have.
</Note>

## Step 1: Install the desktop app

Install with the one-line installer:

```bash theme={"system"}
curl -fsSL https://inference.net/halo/install.sh | sh
```

The installer detects your platform and downloads the matching release: a signed, notarized DMG on Apple Silicon macOS, or a `-Setup.tar.gz` on Ubuntu/Debian x64. You can also grab a build directly from the [releases page](https://github.com/context-labs/halo/releases).

<Note>
  HALO v1 supports **Apple Silicon Macs** and **Ubuntu/Debian Linux (x64)** only. The installer stops with a clear message on Intel Macs, other Linux distributions, and Windows. On a clean Ubuntu/Debian box you may also need a few system libraries first: `sudo apt-get install -y libgtk-3-0 libwebkit2gtk-4.1-0 libayatana-appindicator3-1`.
</Note>

## Step 2: Load the demo traces

Launch the app. After a short welcome, onboarding lands on the **Import Demo Traces** screen. This is the front door for getting data into HALO: import history from **Langfuse** or **Phoenix**, upload a **JSONL** trace export, connect a **local agent**, or load a demo dataset.

<Frame>
  <img src="https://mintcdn.com/kuzco/GcUfkzoVqJBltyHM/images/guides/halo-desktop/hd-import.png?fit=max&auto=format&n=GcUfkzoVqJBltyHM&q=85&s=0baf7220457781ace01c33a54c69087a" alt="The Import Agent Traces onboarding screen with cards for Import from Langfuse, Import from Phoenix, Import JSONL File, Connect Local Agent, Load Demo Traces, and Read Documentation" width="3434" height="2056" data-path="images/guides/halo-desktop/hd-import.png" />
</Frame>

For this guide, click **Load Demo Traces**. The dialog explains exactly what it does: HALO downloads an allowlisted JSONL export from the public [`inference-net/SearchAgentDemoTraces`](https://huggingface.co/datasets/inference-net/SearchAgentDemoTraces) dataset on Hugging Face, caches it beside your local app data, and queues the normal JSONL importer. No arbitrary remote URLs are accepted.

<Frame>
  <img src="https://mintcdn.com/kuzco/GcUfkzoVqJBltyHM/images/guides/halo-desktop/hd-search-traces-import.png?fit=max&auto=format&n=GcUfkzoVqJBltyHM&q=85&s=d95a8afc702700c653ba2c723af640fa" alt="The Load Demo Traces dialog showing the SearchAgentDemoTraces Hugging Face dataset, with Source, Cache, and Import cards and a Load Traces button" width="1638" height="1052" data-path="images/guides/halo-desktop/hd-search-traces-import.png" />
</Frame>

Click **Load Traces**. The dataset is about 1,000 real runs of a pre-instrumented web-search agent (more on it in [Step 5](#step-5-open-a-trace)), and the import usually finishes in under a minute. You can watch it complete on the **Imports** page, which tracks everything you have ever brought into HALO:

<Frame>
  <img src="https://mintcdn.com/kuzco/GcUfkzoVqJBltyHM/images/guides/halo-desktop/he-imports-list-page.png?fit=max&auto=format&n=GcUfkzoVqJBltyHM&q=85&s=2fbeb222e1b66cefebea78cc4c98b1d4" alt="The Imports page showing a completed file import of 1,005 traces and 16,174 observations" width="3436" height="2062" data-path="images/guides/halo-desktop/he-imports-list-page.png" />
</Frame>

<Tip>
  You can come back to this screen anytime. The **Import Data** button in the top right of the Data and Imports pages reopens the same import options, and **Settings → Replay onboarding** restarts the whole flow.
</Tip>

## Step 3: Add a model provider

HALO analysis runs against a model you choose, with your own key. Open **Settings** and click **Add Provider** under **Model providers**.

<Frame>
  <img src="https://mintcdn.com/kuzco/GcUfkzoVqJBltyHM/images/guides/halo-desktop/hd-settings-page.png?fit=max&auto=format&n=GcUfkzoVqJBltyHM&q=85&s=bebee330f0ce24ee204e17e1b7f2507b" alt="The Settings page showing the Model providers section with an Add Provider button, Data Management with database details, and the HALO Configuration section with the engine installed" width="3446" height="2064" data-path="images/guides/halo-desktop/hd-settings-page.png" />
</Frame>

Pick a provider type, which prefills the base URL, then paste your API key:

* **OpenAI** sets `https://api.openai.com/v1`.
* **Anthropic** sets `https://api.anthropic.com/v1`.
* **Custom OpenAI-compatible** lets you point at OpenRouter, Inference (`https://api.inference.net/v1`), or any other compatible endpoint.

<Frame>
  <img src="https://mintcdn.com/kuzco/GcUfkzoVqJBltyHM/images/guides/halo-desktop/hd-add-model-provider.png?fit=max&auto=format&n=GcUfkzoVqJBltyHM&q=85&s=e417cc7483ef883e52f984aa6b0d4ed8" alt="The Add provider dialog with a provider type selector, name, base URL, and API key fields" width="1084" height="1190" data-path="images/guides/halo-desktop/hd-add-model-provider.png" />
</Frame>

The key is stored locally in SQLite, masked in the UI, and never leaves the machine.

While you are in Settings, check the **HALO Configuration** section at the bottom. HALO runs as a local Python engine; this section shows its install status and runtime checks (`git`, `uv`, Python 3.12).

## Step 4: Find your way around

The app has four main pages, all in the left sidebar:

* **Data** is the trace timeline: every trace and session in your local workspace, with search, filters, and summary stats.
* **Analysis** is where HALO runs live: start new runs, watch them stream, and revisit every completed report.
* **Imports** tracks trace history brought in from other tools, with per-import status and counts.
* **Settings** holds model providers, the local database details, and the HALO engine install.

Open **Data**. The stats bar across the top summarizes the workspace (traces, spans, LLM spans, errors, tokens, cost), and each row is one run with its input, output, and duration. Failed runs are tinted red, so problems jump out while scrolling. The left rail filters by time window, status, source, service, agent, and model, and the **Traces / Sessions** toggle switches between individual runs and grouped sessions.

<Frame>
  <img src="https://mintcdn.com/kuzco/GcUfkzoVqJBltyHM/images/guides/halo-desktop/hd-trace-list-page.png?fit=max&auto=format&n=GcUfkzoVqJBltyHM&q=85&s=c38e12c5cbcf50b0ae9b513d6ba3073d" alt="The Data page showing about 1,000 imported traces with filters on the left, summary stats across the top, and failed runs highlighted in red" width="3440" height="2062" data-path="images/guides/halo-desktop/hd-trace-list-page.png" />
</Frame>

<Warning>
  Imported traces keep their **original timestamps**, not the time you imported them. Set the time window to **All time** so the demo dataset shows up, and do the same when you configure the HALO run in [Step 6](#step-6-run-halo).
</Warning>

## Step 5: Open a trace

The demo traces all come from one agent, **Traceable Search Agent**: a compact web-search agent that plans in a scratchpad, searches the web through Tavily, extracts pages, scores sources, and writes a final answer. It ships with deliberate, documented flaws (a heuristic source-quality score, an unstructured scratchpad, no enforced answer schema), which is exactly what makes this dataset a good HALO sandbox. The code lives in [`context-labs/SearchAgentDemo`](https://github.com/context-labs/SearchAgentDemo) (Python) and [`context-labs/SearchAgentDemoTS`](https://github.com/context-labs/SearchAgentDemoTS) (TypeScript); you will clone one in [Step 7](#step-7-hand-the-report-to-a-coding-agent).

Click any row on the Data page to open the trace viewer. The **Timeline** view is a waterfall of every span in the run: the agent loop at the top, then each LLM call, tool call, and retriever call laid out against the clock. It makes the shape of a run obvious at a glance, including what ran serially that could have been parallel, and where the time actually went. Use the **Cost heatmap** toggle to shade spans by spend, and zoom with the controls or by double-clicking a span.

<Frame>
  <img src="https://mintcdn.com/kuzco/GcUfkzoVqJBltyHM/images/guides/halo-desktop/hd-trace-timeline.png?fit=max&auto=format&n=GcUfkzoVqJBltyHM&q=85&s=f5a86f288c2da9b18d1f27df20c3d513" alt="The Timeline view of a single trace, showing a waterfall of OpenAI Chat Completions calls, web search tool calls, and nested tavily.search retriever spans across an 8 second run" width="3440" height="2052" data-path="images/guides/halo-desktop/hd-trace-timeline.png" />
</Frame>

Switch to the **Conversation** view to read the same run as a thread: the user's question, the agent's answer, and an expandable list of every span in between. Click any span to inspect it in the side panel, with the full input and output, model, duration, and cost. Open the first LLM span and you can read the agent's entire system prompt, including its operating loop and its known rough edges.

<Frame>
  <img src="https://mintcdn.com/kuzco/GcUfkzoVqJBltyHM/images/guides/halo-desktop/hd-conversation-view.png?fit=max&auto=format&n=GcUfkzoVqJBltyHM&q=85&s=c84aa82f44f3409b2619119fa67ab76f" alt="The Conversation view of a trace with the span list expanded and a side panel showing an LLM span's system prompt, model, and timing details" width="3440" height="2064" data-path="images/guides/halo-desktop/hd-conversation-view.png" />
</Frame>

Skim a handful of runs, especially the red ones. You will spot failed searches and retry loops by eye. That is the point of the next step: HALO reads all 1,000 runs and finds the patterns for you.

## Step 6: Run HALO

Click **Run Analysis** in the top right of the Data page (or start from the **Analysis** page). The dialog is where you scope the run:

* **Session group or Trace group** picks the unit of analysis.
* The filters (search, window, status, source, service, agent, observed model, scope) narrow which telemetry HALO reads. For the demo dataset, set the window to **All time** and leave the rest open. The live counts at the bottom confirm what the run will cover, about 1,000 traces here.
* **Provider and model** select the provider you saved in [Step 3](#step-3-add-a-model-provider) and which of its models does the analysis.
* **Title and prompt** name the run and tell HALO what to look for.

<Frame>
  <img src="https://mintcdn.com/kuzco/GcUfkzoVqJBltyHM/images/guides/halo-desktop/hd-analysis-modal.png?fit=max&auto=format&n=GcUfkzoVqJBltyHM&q=85&s=5e35bd423d077decec21f3fa987bdc7d" alt="The Run Analysis dialog with Session group and Trace group tabs, telemetry filters, live counts showing 1,000 traces, and provider and model selectors" width="1456" height="1756" data-path="images/guides/halo-desktop/hd-analysis-modal.png" />
</Frame>

A specific prompt gives sharper results. This run used:

```text theme={"system"}
Analyze these traces. Identify the most important failures, latency bottlenecks,
confusing tool behavior, and concrete improvements for the developer.
```

Click **Start run**. The run moves through **Queued → Export → Analysis → Done**, and you can watch every agent step stream in as the engine digs through the traces. The right rail tracks the run details: target, provider, model, and the trace, session, and span counts as they are exported.

<Frame>
  <img src="https://mintcdn.com/kuzco/GcUfkzoVqJBltyHM/images/guides/halo-desktop/hd-halo-run-queued.png?fit=max&auto=format&n=GcUfkzoVqJBltyHM&q=85&s=89b033961874cafd0a601ebcb9c40fb2" alt="A HALO run just after starting, showing the analysis prompt, the Queued, Export, Analysis, Done status pipeline, and run details in the right rail" width="3438" height="2062" data-path="images/guides/halo-desktop/hd-halo-run-queued.png" />
</Frame>

Expect several minutes for a dataset this size; this run covered 1,000 traces and 16,000+ spans in about nine minutes. When it finishes, the report renders in place: ranked findings with citations back to the exact traces each one came from. Click a citation chip to drop into that trace and confirm the finding before you act on it.

<Frame>
  <img src="https://mintcdn.com/kuzco/GcUfkzoVqJBltyHM/images/guides/halo-desktop/hd-completed-run-top.png?fit=max&auto=format&n=GcUfkzoVqJBltyHM&q=85&s=6f511eb41b712575805079006cf08d83" alt="A completed HALO report showing ranked findings with trace citations, section chips for failures and latency bottlenecks, and an Act on this report panel in the right rail" width="3436" height="2056" data-path="images/guides/halo-desktop/hd-completed-run-top.png" />
</Frame>

On this dataset, HALO's top findings included:

* **A deterministic tool-argument failure.** The model passes `topic="health"` or `topic="sports"` to the Tavily search tool, which only accepts `general`, `news`, or `finance`, so those searches fail every single time. The fix is to encode the constraint as an enum in the tool schema.
* **Error-prone search and extraction that triggers rework loops.** Failed searches and extractions send the agent back through extra LLM deliberation and retries, burning latency and tokens.
* **Latency dominated by sequential LLM calls.** The slowest runs stack around six back-to-back chat completions plus serial searches that could run concurrently.
* **Confusing telemetry.** The tool wrapper span and the underlying provider span both report ERROR for the same root cause, and the wrapper span is missing its real inputs, which makes debugging and error counts misleading.

The report closes with a prioritized action plan, ordered by return on effort:

<Frame>
  <img src="https://mintcdn.com/kuzco/GcUfkzoVqJBltyHM/images/guides/halo-desktop/hd-completed-run-fix-list.png?fit=max&auto=format&n=GcUfkzoVqJBltyHM&q=85&s=bb2855a499912964428157a9ef10a21b" alt="The developer-focused action plan from the HALO report, listing five fixes ranked by ROI, from Tavily topic correctness through cleaning up tracing semantics" width="1468" height="486" data-path="images/guides/halo-desktop/hd-completed-run-fix-list.png" />
</Frame>

<Tip>
  The chat box under the report asks follow-up questions by re-running HALO over the same traces with full context. Use it to drill into a finding ("show me more traces with the topic failure") without configuring a new run.
</Tip>

## Step 7: Hand the report to a coding agent

The report is a ranked, cited to-do list for the agent's codebase, and the desktop app hands it off directly. The **Act on this report** panel next to every completed run has one-click buttons for **Open in Cursor**, **Open in Claude Code**, and **Open in Codex**, plus **Copy prompt** for any other tool. No MCP server, no wiring.

<Frame>
  <img src="https://mintcdn.com/kuzco/GcUfkzoVqJBltyHM/images/guides/halo-desktop/hd-act-on-report-buttons.png?fit=max&auto=format&n=GcUfkzoVqJBltyHM&q=85&s=8297a6e450ca9b3bcd05e5a67097bb0c" alt="The Act on this report panel with Open in Cursor, Open in Claude Code, and Open in Codex buttons and a Copy prompt option" width="702" height="496" data-path="images/guides/halo-desktop/hd-act-on-report-buttons.png" />
</Frame>

The demo traces came from the search agent repo, so that is where the fixes belong. Clone it first, in whichever language you prefer (the two flavors have the same tools, the same deliberate flaws, and produce the same findings):

<CodeGroup>
  ```bash Python theme={"system"}
  git clone https://github.com/context-labs/SearchAgentDemo.git
  cd SearchAgentDemo
  ```

  ```bash TypeScript theme={"system"}
  git clone https://github.com/context-labs/SearchAgentDemoTS.git
  cd SearchAgentDemoTS
  ```
</CodeGroup>

Then click the button for your coding agent and run it from the cloned repo. Every run saves its full report to disk (the paths are listed under **Artifacts** in the run details), and the handoff prompt points the coding agent at that file with instructions along the lines of:

```text theme={"system"}
Read the HALO trace-analysis report at
~/Library/Application Support/net.inference.halo/halo-runs/<run-id>/report.md
and act on its findings in this codebase: fix the identified failures and
implement the recommended improvements.
```

For this dataset, the fixes land in the tool schemas (`tools.py` / `tools.ts`), the agent loop (`agent.py` / `agent.ts`), and the tracing setup. The report's citations mean the coding agent is not guessing: every recommendation traces back to specific runs you can open in the viewer.

## Step 8: Close the loop

A fix is not done until new traces from the changed code confirm it. This is where the desktop app's live mode comes in: the same agent repo can stream traces straight into your local timeline while it runs, with nothing crossing the network beyond the agent's own model calls.

1. In the app, open **Import Data → Connect Local Agent**. It shows the local ingest endpoint. Copy the repo's env file and point the agent at it:

   ```bash theme={"system"}
   cp .env.example .env
   ```

   ```bash theme={"system"}
   # .env
   INFERENCE_API_KEY=sk-...                                # powers the agent's model calls
   CATALYST_OTLP_ENDPOINT=http://127.0.0.1:8799/v1/traces  # send traces to the desktop app, not the cloud
   ```

   `INFERENCE_API_KEY` is what the agent uses to call its model; point it at any provider by also setting `INFERENCE_BASE_URL` (it defaults to Inference's OpenAI-compatible endpoint). The `CATALYST_OTLP_ENDPOINT` override is the whole trick: instead of shipping spans to the cloud, the agent posts them to the desktop app listening on `127.0.0.1:8799`.

2. Run a batch from the repo's bundled query dataset against your patched code. The query set is fixed, so the only variable between before and after is your fix:

   <CodeGroup>
     ```bash Python theme={"system"}
     uv run search-agent-batch --limit 5
     ```

     ```bash TypeScript theme={"system"}
     bun run search-agent-batch --limit 5
     ```
   </CodeGroup>

   Watch the traces land in the Data page as each run finishes.

3. Run HALO again, scoped to the new traces (a recent time window or the new session IDs), and compare the two reports. The findings you fixed should be gone or diminished; pick up the next one.

That is the whole HALO loop, start to finish, running entirely on your machine. Once it clicks here, point the same loop at your own agent.

## Bring your own traces

You do not have to use the demo dataset. The same **Import Agent Traces** options from [Step 2](#step-2-load-the-demo-traces) work on your real data, which makes the desktop app a low-commitment way to try HALO on the agent you actually run:

* **Import from Langfuse.** Paste a Langfuse project's API URL and key pair (public and secret). HALO pulls your trace history over the Langfuse public API and stores it locally. If you would rather keep your existing pipeline and try HALO without importing, you can instead point the [Langfuse SDK at Catalyst](/integrations/traces/langfuse) with an env-var switch.
* **Import from Phoenix.** Bring historical traces from an Arize Phoenix project into the local timeline the same way.
* **Import JSONL.** Any JSONL trace export with one span per line works, including OpenTelemetry and Catalyst exports.
* **Connect Local Agent.** Stream traces live from any Catalyst- or OpenTelemetry-instrumented agent by pointing its OTLP endpoint at `http://127.0.0.1:8799/v1/traces`, as in [Step 8](#step-8-close-the-loop).

<Tip>
  HALO groups and analyzes traces by agent identity. For the sharpest reports from imported data, make sure your top-level spans carry a stable `agent.name` (and ideally `agent.id`). For Langfuse specifically, see [Group by agent](/integrations/traces/langfuse#group-by-agent).
</Tip>

## Self-hosting and production

A common question: can you run this in production? Two answers, depending on what you mean.

* **The desktop app** is a single-user, local-first tool. It is ideal for exploring, debugging, and iterating on an agent on your own machine. It is not designed to be a shared, always-on production service.
* **The HALO engine** is open source and MIT licensed ([`context-labs/halo`](https://github.com/context-labs/halo), [`halo-engine` on PyPI](https://pypi.org/project/halo-engine/)). You can self-host it: install the CLI, point it at exported traces, and run it anywhere, including in CI against a fresh trace export on every deploy. That is the self-hosted production path for the analysis step itself.

For continuous, team-scale observability (always-on trace ingest, multiple users, scheduled HALO runs, [Signals](/guides/measure-agent-quality), and alerting), the [hosted Catalyst platform](/guides/try-halo-demo-repo) is the path we recommend. The instrumentation is identical, so anything you build locally moves over by changing where traces are sent.

## Where to go next

<CardGroup cols={2}>
  <Card title="Try the hosted version" icon="cloud" href="/guides/try-halo-demo-repo">
    The same loop on the hosted Catalyst dashboard, with scheduled runs, Signals, and the MCP server.
  </Card>

  <Card title="Do this on your own agent" icon="arrows-rotate" href="/guides/optimize-an-agent-end-to-end">
    Run the trace, analyze, fix loop against your real app from instrumentation onward.
  </Card>

  <Card title="Bring your Langfuse traces" icon="link" href="/integrations/traces/langfuse">
    Point the Langfuse SDK at Catalyst with an env-var switch, no code changes.
  </Card>

  <Card title="HALO on GitHub" icon="github" href="https://github.com/context-labs/halo">
    The open-source HALO desktop app, engine, and methodology. MIT licensed.
  </Card>
</CardGroup>
