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

# Company Brain Q&A

> Ask one question across your company's database, support tickets and documents, and get one answer that joins them

Who owns the open ticket, which team they are on, and what the meeting decided: today that is three tools and a lot of copying. Here it is one answer.

## What You'll Build

Your SQL database, your ticket exports and a folder of documents go into one cognee memory. A graph model you control tells cognee which people, teams, projects, customers and tickets to extract, so the same person in all three sources becomes one node. Then you ask questions no single source can answer, and browse the graph in a UI.

Building the memory takes three `cognee.remember` calls, one per source, all with the same graph model, and answering a question takes one `cognee.recall` call.

The complete cookbook is
[`examples/cookbooks/company_brain/company_qa/`](https://github.com/topoteretes/cognee/tree/dev/examples/cookbooks/company_brain/company_qa).

## Try It on Sample Data

The sample is Acorn Analytics, a fictional company: an HR and project database, two ticket exports (a support desk export and a CSV of escalations that Customer Success keeps in a spreadsheet) and three documents. The escalated ticket in the CSV says who is assigned to Brightline Retail's open issue. Only the database says which team she is on. Only a meeting note says which fix was decided. You need only an [LLM key](/setup-configuration/llm-providers), no data of your own.

```bash theme={null}
git clone https://github.com/topoteretes/cognee.git && cd cognee
uv sync
echo 'LLM_API_KEY="your-key"' >> .env
```

`LLM_API_KEY` alone is enough for OpenAI, cognee's default for both the LLM and the embeddings. Other providers, such as Anthropic, Gemini, Azure OpenAI, AWS Bedrock or a local model through Ollama, need a few more lines in the same `.env`: [LLM Providers](/setup-configuration/llm-providers#provider-setup-guides) and [Embedding Providers](/setup-configuration/embedding-providers#provider-setup-guides) list them for each provider. Set both, because embeddings you leave at the default still need an OpenAI key.

<Tabs>
  <Tab title="Terminal">
    ```bash theme={null}
    uv run python examples/cookbooks/company_brain/company_qa/company_qa.py --sample
    ```
  </Tab>

  <Tab title="Coding agent">
    The cognee repo ships a skill for this cookbook, [`.agents/skills/company-brain-company-qa/SKILL.md`](https://github.com/topoteretes/cognee/blob/dev/.agents/skills/company-brain-company-qa/SKILL.md). Claude Code and Codex find it on their own when you open them in the cognee folder. Ask in plain words, or type `/company-brain-company-qa` in Claude Code:

    ```text theme={null}
    Who is handling Brightline Retail's open ticket, and what fix was decided?
    ```

    With no sources given, it runs on the sample company and says so. To use your own data, tell it your database URL, ticket export and docs folder; the skill runs `--check` first and tells you what is missing.
  </Tab>
</Tabs>

```text theme={null}
[setup] CLEAR: the cookbook's dataset is forgotten before this run.
[setup] Wrote the sample from setup.py.
[clear] Nothing to forget: the dataset company_qa does not exist yet.
[ingest] Remembered the database (employee_profiles, project_profiles, customer_profiles)
[ingest] Remembered the tickets in .../company_qa/sample/tickets.json, .../company_qa/sample/escalations.csv
[ingest] Remembered the docs in .../company_qa/sample/docs
...
[ask] Q: Who is handling Brightline Retail's open high-priority ticket, which team are they on, and what fix was decided for it?
[ask] A: Dana Kim is handling it. They’re on the Search team, and the decided fix is to update the Atlas indexer to read every catalog-feed file and re-index the catalog.
```

"Dana Kim is handling it" comes from ticket T-1041 in the escalations CSV. "The Search team" comes from the HR database. The fix comes from the Atlas weekly sync notes. The answer joins them because Dana Kim is one node in the graph, not three. The first run has nothing to forget; a later sample run prints `[clear] Forgot the dataset company_qa` instead. Your wording will differ from run to run.

## Run It on Your Data

* `--database` (optional): a SQLAlchemy URL such as `postgresql://...` or `sqlite:///path/to.db`, read through [dlt](/integrations/dlt-integration)'s `sql_database`. Add `--tables a,b` to read only those tables or views.
* `--tickets` (optional): one or more JSON or CSV exports from your support desk.
* `--docs` (optional): a folder of meeting notes, postmortems or memos.
* Pass at least one source. Without any, the cookbook runs on the sample.
* Node.js 20+ and npm, only for `--ui`. Without them, cognee falls back to Docker.

```bash theme={null}
uv run python examples/cookbooks/company_brain/company_qa/company_qa.py --check \
    --database postgresql://user:password@host/hr --tickets ~/exports/tickets.json \
    --docs ~/Documents/company
uv run python examples/cookbooks/company_brain/company_qa/company_qa.py \
    --database postgresql://user:password@host/hr --tables employees,projects \
    --tickets ~/exports/tickets.json --docs ~/Documents/company \
    --ask "Who owns the open billing incident, and what did we decide to do about it?"
```

`--check` reports what is missing without doing any work. Running it again skips content cognee already holds; an edited file is remembered as a new document, and its old version stays. Add `--clear` to forget the dataset first and start over from your sources as they are now. Later questions don't need the sources again: `uv run python examples/cookbooks/company_brain/company_qa/scripts/ask.py "question"`.

## How It Works

### Step 1: Start From an Empty Memory

Source: [`scripts/clear.py`](https://github.com/topoteretes/cognee/blob/dev/examples/cookbooks/company_brain/company_qa/scripts/clear.py)

This step forgets what an earlier run remembered, so old copies never mix with new ones. It runs only with `--clear`, which a sample run turns on by default; `--no-clear` keeps the dataset.

```python theme={null}
await clear()
```

cognee's part is one call: [`cognee.forget(dataset="company_qa")`](/core-concepts/main-operations/forget), which deletes the dataset and everything extracted from it. On your own data, use `--clear` only to start over.

### Step 2: Remember Your Company's Sources

Source: [`scripts/ingest.py`](https://github.com/topoteretes/cognee/blob/dev/examples/cookbooks/company_brain/company_qa/scripts/ingest.py)

This step saves each source you pass, so every later question can use all of them. With `--sample`, the arguments point at the sample company.

```python theme={null}
await ingest(args.database, tables, args.tickets, args.docs)
```

It reads every row of the tables you name (all tables and views without `--tables`), every ticket file you pass, and every document in the folder. Each source gets one `cognee.remember` call with its own [node set](/core-concepts/further-concepts/node-sets) (`database`, `tickets`, `docs`), a tag that lets you later recall from one source alone. All three pass `graph_model=CompanyGraph` from `models.py`: the node types the LLM extracts. Each type declares `identity_fields`, so the same name gives the same node id, and that is what links the sources. Tickets and docs also pass `preferred_loaders=["csv_loader"]`, so a CSV file is read as text and extracted with the graph model, rather than stored as plain table rows that never link to the other sources.

### Step 3: Answer a Question Across Sources

Source: [`scripts/ask.py`](https://github.com/topoteretes/cognee/blob/dev/examples/cookbooks/company_brain/company_qa/scripts/ask.py)

This step answers your question from everything the previous step remembered. It runs when you pass `--ask`; the sample run asks its own question.

```python theme={null}
await ask(args.ask)
```

cognee's part is one call: `cognee.recall(question, datasets=["company_qa"])`. [`recall`](/core-concepts/main-operations/recall) with no `query_type` picks the retrieval strategy itself. For a plain question that is `HYBRID_COMPLETION`, which searches the text and the graph together and writes one answer. There is no node set filter, so the answer can draw on all three sources at once.

### Step 4: Browse the Graph

Source: [`scripts/ui.py`](https://github.com/topoteretes/cognee/blob/dev/examples/cookbooks/company_brain/company_qa/scripts/ui.py)

This step opens the graph in your browser. It runs when you pass `--ui`.

```python theme={null}
await open_ui()
```

The script starts cognee's API server inside this process, next to the local databases cognee already has open, then starts the UI with `cognee.start_ui`. Open [http://localhost:3000](http://localhost:3000), sign in with the prefilled default user, and select the `company_qa` dataset. You see one node per person, linked to their team, projects, tickets and manager. Ctrl+C stops both.

## Make It Yours

* **Model your own company.** Edit `models.py`: add the entities your data talks about, drop the ones it doesn't, and keep `identity_fields` on every type so sources still link. See [Custom Graph Model](/guides/custom-graph-model).
* **Add the rest of your company's data.** Your company's knowledge also lives in mail, shared drives, meeting notes and issue trackers. Add one more `remember` call to `scripts/ingest.py` for each source, with its own node set and the same `graph_model=CompanyGraph`, so its people and projects merge with the nodes you already have. cognee ships connectors you pass straight to `remember`: [`google_drive_source`](/guides/google-drive), [`gmail_source`](/guides/gmail-ingestion) and [`linear_source`](/integrations/dlt-integration#linear-connector). For Granola, the [Follow-Up Agent](/cookbooks/follow-up-agent) cookbook has a small client that reads your meeting notes. Any other API or database loads through [dlt](/integrations/dlt-integration).
* **Feed it readable rows.** Point `--tables` at views that join your tables into `id`, `title` and `content` columns, like the `*_profiles` views in `setup.py`. The LLM extracts sentences better than bare foreign keys.
* **Ask one source at a time.** Recall with `query_type=SearchType.CHUNKS` and `node_name=["tickets"]` to see what the ticket export alone says. [NodeSet Grouping](/guides/nodeset-grouping) shows how scoping works.
* **Let your coding agent ask.** Keep `scripts/ui.py` running and connect Claude Code or Codex through the [cognee MCP server](/cognee-mcp/mcp-overview) with `--api-url http://localhost:8000`. The agent then reads the same graph as the UI. The cookbook README has the exact commands.

## Clean Up

```bash theme={null}
uv run cognee-cli forget --dataset company_qa
```

To start over completely, also delete `sample/` in the cookbook folder.

<Columns cols={2}>
  <Card title="Custom Graph Model" icon="share-2" href="/guides/custom-graph-model">
    Define the node types cognee extracts from your data.
  </Card>

  <Card title="Follow-Up Agent" icon="list-checks" href="/cookbooks/follow-up-agent">
    Build another one: turn your latest call into next steps.
  </Card>

  <Card title="Personalized Email" icon="mail-check" href="/cookbooks/personalized-email">
    Build another one: email replies that know what you promised.
  </Card>

  <Card title="Self-Hosted AI Companion" icon="notebook-pen" href="/cookbooks/self-hosted-companion">
    Build another one: a chat companion that knows your notes.
  </Card>
</Columns>


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