---
name: onta
description: Use this skill whenever the user asks about data that lives in an Onta context graph (a knowledge graph queried in natural language), wants to ingest a CSV into one, create or delete a graph, explore or evolve its ontology in plain English, or enrich / clean / deduplicate / web-ingest data into it. Covers MCP setup and all 15 MCP tools — read tools (ask, search, list_knowledge_graphs, view_ontology, list_jobs, get_job, wait_for_job), write tools (ingest_csv, create_knowledge_graph, delete_knowledge_graph, evolve_ontology, apply_ontology_change, apply_ontology_changes, schedule), and the conversational `agent` front door that plans-then-confirms enrichment, cleaning, dedupe, and web ingestion.
---

# Onta

Onta turns your data into queryable context graphs (knowledge graphs). Ingest a CSV once, Onta infers an ontology (types, attributes, relationships), and then you can ask natural-language questions that get translated to SPARQL and answered against the graph (use `search` for source-cited entity snippets). Onta is not read-only: agents can also **create and delete graphs, ingest and merge data, evolve the schema in plain English, and enrich / clean / deduplicate / web-ingest** through the conversational `agent` tool.

This skill teaches you how to use Onta correctly. Follow it instead of guessing.

## When to use this skill

Activate this skill when any of the following is true:

- The user mentions "onta", "context graph", "knowledge graph", "kg", or references a graph by name.
- The user wants to ask analytical questions about their data ("how many", "which has the most", "average price by…") and Onta is configured in the environment.
- The user hands you a CSV and wants to query it (or merge it into an existing graph) rather than parse it cell-by-cell.
- The user wants to explore or evolve an ontology, list available graphs, or create/delete a graph.
- The user wants to **enrich, clean, deduplicate, or web-ingest** data into a graph — route these through the `agent` tool.

If the user just wants to read or transform a CSV row-by-row, this skill is **not** the right tool — use normal file tools.

## Setup: wire up the MCP server

Onta exposes its capabilities through an MCP server published to npm as `@onta/mcp`. Before you can call any tool, the server must be registered in the agent harness's MCP config (e.g. `~/.claude/mcp.json` for Claude Code, the Cursor MCP settings panel, etc.):

```json
{
  "mcpServers": {
    "onta": {
      "command": "npx",
      "args": ["-y", "@onta/mcp"],
      "env": {
        "ONTA_API_KEY": "your-key"
      }
    }
  }
}
```

- **`ONTA_API_KEY`** (required) — an API key from your Onta dashboard. Do not hardcode a real key into shared files.
- **`ONTA_API_URL`** (optional) — the backend to connect to. Defaults to `https://api.onta.sh`. Override only when self-hosting or pointing at a local server.
- **Legacy env names still work.** `COGRAPH_API_KEY` / `COGRAPH_API_URL` and `OMNIX_API_KEY` / `OMNIX_API_URL` are honored as aliases for backward compatibility (Onta's lineage is omnix → cograph → onta). Prefer the `ONTA_*` names for new configs.
- **Legacy package names.** Older configs may reference `onta-mcp` or `cograph-mcp`; update them to `@onta/mcp`.

If the `onta` MCP server is not listed among your available tools, tell the user: *"I don't see the Onta MCP server registered. Add the config above to your MCP client and restart the session."* Do **not** try to `curl` the REST API as a workaround unless the user explicitly asks.

## The 15 tools

All Onta tool calls go through the `onta` MCP server. There are 15 tools, grouped by whether they read or write the graph. Know them.

### Read tools (safe — never mutate a graph)

#### `list_knowledge_graphs`
No parameters. Returns the name and description of every graph the current tenant can see. **Always call this first** when you don't know which graph to query — guessing `kg_name` leads to "graph not found" errors that waste turns.

#### `ask`
Natural-language question → exact answer. Parameters: `question` (string, required); `kg_name` (string, optional — omit only if the session is scoped to one graph). Returns an `answer` (human-readable) and an `explanation` of how it was derived. Show the `answer` by default; read the `explanation` if asked how it was computed or the result looks wrong. For source-cited entity snippets, use `search`. This is the main analytical loop.

#### `search`
Hybrid semantic + keyword search over entities in a graph — use it to find matching records by fuzzy description when you don't have an exact analytical question. Complements `ask` (which computes aggregate answers); `search` retrieves the entities themselves.

#### `view_ontology`
No parameters. Returns the full schema (types, attributes with datatypes, relationships between types) for this tenant. Call it before writing any non-trivial `ask` question — using the exact ontology-aligned attribute and type names makes the translator dramatically more accurate.

#### `list_jobs`
Lists recent asynchronous jobs (ingestion, enrichment, and other long-running operations) with their status. Use it to see what's in flight or recently finished.

#### `get_job`
Fetches the status and result of a single job by id. Use it to poll a specific long-running operation.

#### `wait_for_job`
Blocks until a job reaches a terminal state (completed/failed) and returns its result. Prefer this over hand-rolled polling when you need to wait for an ingest or enrichment to finish before the next step.

### Write tools (mutate a graph — confirm intent first)

#### `ingest_csv`
CSV → entities and triples, with the schema inferred automatically. Parameters: `file_path` (string, required — absolute path to the CSV on the machine running the MCP server); `kg_name` (string, required — kebab-case, e.g. `austin-zillow`); optionally `join_on` — when set, rows are **merged onto existing entities** that match on that key instead of minting duplicates. Schema is inferred with a single LLM call against headers + sample rows; do not pre-process the CSV yourself.

#### `create_knowledge_graph`
Creates a new, empty context graph so you can populate it deliberately (e.g. before a targeted ingest or an ontology-first workflow). Use kebab-case names.

#### `delete_knowledge_graph`
Permanently deletes a graph and its data. Destructive and irreversible — **always confirm with the user before calling**, and never delete a graph you weren't explicitly asked to.

#### `evolve_ontology`
Evolve the schema by describing the change in plain English — you do **not** need to know exact type/attribute/relationship names. Parameters: `ask` (string, required — e.g. "track which company a person works for"); `knowledge_graph` (string, optional). Returns a `summary`, the `applied` changes (high-confidence edits committed automatically), and any `proposals` (ambiguous or new-type changes to confirm). The resolver reuses existing types where it can. Show the `summary` and `applied`; if `proposals` came back, surface them and confirm before applying.

#### `apply_ontology_change`
Commits **one** proposal returned by `evolve_ontology`. Parameter: `proposal` (object, required) — pass a proposal object through unchanged. Stateless and idempotent (applying twice is a no-op). Do not hand-craft change objects — only pass back proposals the resolver produced.

#### `apply_ontology_changes`
Commits **several** `evolve_ontology` proposals in one call — the batch form of `apply_ontology_change`. Use it when the user confirms multiple proposals at once.

#### `schedule`
Sets up a recurring job that watches a source and **notifies on change** (e.g. re-check a dataset on a cadence and report what's new). Use it when the user wants ongoing monitoring rather than a one-shot operation.

### `agent` — reads and writes (the conversational front door)

`agent` is the natural-language entry point for anything beyond a single primitive call. Describe the goal in plain language and it **plans** the work — including **enrichment, cleaning, deduplication, and web ingestion** — and returns that plan.

- Nothing mutating happens on the planning call. To **execute** a plan, call `agent` again with the returned `confirm_plan_id`. This plan-then-confirm loop is the mutating path for enrichment, dedupe, cleaning, and web-ingest — there is no separate one-shot tool for those.
- Use `agent` when the request is conversational or multi-step ("enrich these companies with their industry from the web", "dedupe the customer list", "clean up the messy address column"), and reach for the primitive tools above when you already know the exact single operation.

## The standard workflow

For most read tasks, follow this sequence:

1. **Discover.** Call `list_knowledge_graphs`. If the target graph doesn't exist and you have a CSV, ingest it; if it doesn't exist and you don't have a CSV, ask the user (or `create_knowledge_graph` if they want to build one from scratch).
2. **Orient.** Call `view_ontology` and skim the types/attributes relevant to the question. This is cheap — do it even if you think you know the schema.
3. **Ask.** Call `ask` with a question phrased using the ontology's attribute and type names. Pass `kg_name` explicitly.
4. **Report.** Return the `answer`. For follow-ups, reuse the same graph — don't re-run discovery unless something changed.

Skipping step 2 is the most common failure mode. Don't skip it.

## Writing good questions for `ask`

The `ask` tool translates natural language to SPARQL using the ontology as context. You'll get better answers if you:

- **Use the exact attribute names from `view_ontology`.** If the ontology calls it `price`, say "price", not "cost".
- **Name the entity type explicitly.** "How many `PropertyListing` entities in Austin?" beats "How many are in Austin?".
- **Keep one question per call.** Don't chain "X and also Y" — call `ask` twice.
- **Be quantitative when possible.** "Which category has the highest average price?" is easier than "What's interesting about categories?".

## Ingesting and writing safely

When the user hands you a new CSV:

1. Confirm the **absolute path** — the MCP server needs a path it can actually open.
2. Propose a `kg_name` and confirm it. If the data should **extend an existing graph** rather than start a new one, use `join_on` to merge onto matching entities instead of ingesting under a fresh name.
3. Call `ingest_csv`. Large files take several seconds — this is normal; use `wait_for_job` / `get_job` if you need to block on completion.
4. After ingestion, call `view_ontology` to see what Onta inferred. Summarize it ("Onta detected a `PropertyListing` type with attributes price, bedrooms, city…") before asking what the user wants to know.
5. If the inferred ontology looks obviously wrong (e.g. a relationship treated as a string attribute), tell the user — don't silently query broken data. Fix schema with `evolve_ontology`.

General write hygiene:

- **Destructive calls need explicit confirmation.** Confirm before `delete_knowledge_graph` and before applying ontology changes the user hasn't approved.
- **Enrichment / cleaning / dedupe / web-ingest go through `agent`.** Present the returned plan to the user, then execute with `confirm_plan_id` once they approve — don't auto-confirm mutating plans.
- Do **not** re-ingest the same CSV to "refresh" unless the file actually changed.

## Failure recovery

- **`list_knowledge_graphs` returns empty:** The tenant has no data yet. Offer to ingest a CSV or `create_knowledge_graph`.
- **`ask` returns an empty or zero answer:** Don't assume there's no data. Call `view_ontology` and check the attribute names. Retry once with corrected terminology; if still empty, say so and suggest a broader question. `search` can help confirm whether matching entities exist at all.
- **`ask` raises a SPARQL error:** Usually a field the ontology doesn't have. Re-read the ontology and rephrase.
- **`ingest_csv` fails:** Check the path is absolute and the file exists. If it does, report the error verbatim.
- **A job is slow or stuck:** Use `list_jobs` / `get_job` to inspect status, and `wait_for_job` to block on a specific one.
- **The MCP server isn't available:** See the setup section. Do not fall back to writing SPARQL by hand against an unknown endpoint.

## What Onta is not

- **Not a row-by-row spreadsheet editor.** There is no "edit cell 3 of row 7" tool. To change source *data*, re-ingest the corrected file (use `join_on` to merge). To reshape *structure*, evolve the ontology. To fill or fix *values at scale*, use `agent` enrichment/cleaning.
- **Not multi-graph join-aware in one `ask`.** `ask` operates on one graph at a time. To combine graphs, run separate asks and combine the answers, or merge the sources into one graph via `ingest_csv` + `join_on`.

## Quick reference

| Situation | Tool |
|---|---|
| "What graphs do I have?" | `list_knowledge_graphs` |
| "What's in this graph?" / "What fields are there?" | `view_ontology` |
| Any analytical question about the data | `ask` |
| Find records matching a fuzzy description | `search` |
| New CSV the user wants to query | `ingest_csv` → `view_ontology` → `ask` |
| Add CSV rows onto an existing graph | `ingest_csv` with `join_on` |
| Start an empty graph / remove one | `create_knowledge_graph` / `delete_knowledge_graph` |
| "Track / record / link …" (new field, relationship, or type, in plain English) | `evolve_ontology` |
| Confirm one / several proposals from `evolve_ontology` | `apply_ontology_change` / `apply_ontology_changes` |
| Enrich, clean, dedupe, or web-ingest | `agent` → re-call with `confirm_plan_id` |
| Watch a source and get notified on change | `schedule` |
| Check / wait on a long-running job | `list_jobs` / `get_job` / `wait_for_job` |

When in doubt: **discover, orient, ask** — and route anything conversational or mutating-at-scale through `agent`.
