> ## 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.

# Agentic Procurement Decisions

> Build an agent that researches vendor conversations, purchase history, and policy in separate memory categories, then recommends a vendor with evidence

Your team is about to sign off on 50 laptops, and the evidence for that call is scattered across two vendor sales conversations, a file of past purchase records, and a procurement policy document. A procurement agent has to read all three, keep them straight, and justify whichever vendor it picks.

## What You'll Build

Four procurement documents — two vendor conversations, a purchase-history record, and the company's procurement policies — go into cognee memory under three separate category labels. The agent then runs a research phase: nine questions, each answered only from the category that can answer it, so pricing questions never get answered from the policy file and rating questions never get answered from a sales pitch. The nine question-and-answer pairs are compiled into a single evidence block, and one final LLM call turns that block into a vendor recommendation justified by the research it just did.

The complete runnable script is
[`examples/demos/agentic/agentic_reasoning_procurement_example.py`](https://github.com/topoteretes/cognee/blob/main/examples/demos/agentic/agentic_reasoning_procurement_example.py) —
this page walks through its key moments rather than reproducing it.

## Features in Play

* [NodeSets](/core-concepts/further-concepts/node-sets) — labels each document with its memory category at write time, and scopes each recall to one category at read time
* [Remember](/core-concepts/main-operations/remember) — ingests the four documents into three labeled slices of one graph
* [Recall](/core-concepts/main-operations/recall) — answers each research question against a single category, via `node_name`
* [Inspecting Graph Completion Context](/guides/graph-completion) — `SearchType.GRAPH_COMPLETION` is the search type behind every research answer, grounding it in graph triplets
* [Low-Level LLM](/guides/low-level-llm) — `LLMGateway.acreate_structured_output` makes the final vendor call from the compiled evidence, with no retrieval of its own

## Before You Start

* Complete [Quickstart](/getting-started/quickstart) to understand basic operations
* Ensure you have [LLM Providers](/setup-configuration/llm-providers) configured — the research phase and the final decision are both live LLM calls
* Use Ladybug or Neo4j as your [graph store](/setup-configuration/graph-stores): node sets are only supported on those two backends. The script sets `GRAPH_DATABASE_PROVIDER` to `ladybug` itself, before importing cognee, so no configuration is needed — but a `GRAPH_DATABASE_PROVIDER` in your environment will not win
* Run it from a checkout of the cognee repo: it reads its four `.txt` inputs from the sibling `agentic_reasoning_procurement_example_data/` folder, and loads your `.env` with `load_dotenv()`
* The script starts with `cognee.forget(everything=True)`, so point it at a scratch instance rather than memory you want to keep — see [Forget](/core-concepts/main-operations/forget)

## How It Works

### Stage 1: Categorize Memory by Node Set

```python theme={null}
        # Initializing and pruning databases
        await cognee.forget(everything=True)

        # Store data in different memory categories
        await cognee.remember(
            data=[vendor_conversation_text_techsupply, vendor_conversation_text_office_solutions],
            node_set=["vendor_conversations"],
            self_improvement=False,
        )

        await cognee.remember(
            data=previous_purchases_text,
            node_set=["purchase_history"],
            self_improvement=False,
        )

        await cognee.remember(
            data=procurement_preferences_text,
            node_set=["procurement_policies"],
            self_improvement=False,
        )
```

Three `remember()` calls write into one graph but tag their data with three different node sets: `vendor_conversations`, `purchase_history`, and `procurement_policies`. Those labels are what make the research phase possible — without them, a question about vendor ratings would retrieve sales-pitch text just as readily as the actual rating records.

### Stage 2: Scope Every Recall to One Category

```python theme={null}
    async def search_memory(self, query, search_categories=None):
        """Search across different memory layers"""
        results = {}
        for category in search_categories:
            category_results = await cognee.recall(
                query_type=SearchType.GRAPH_COMPLETION,
                query_text=query,
                node_name=[category],
                top_k=30,
            )
            results[category] = category_results

        return results
```

`node_name` restricts retrieval to the node set named by the category, so each answer is grounded in one memory layer only. `SearchType.GRAPH_COMPLETION` means the answer is generated from graph triplets rather than raw chunks, and `top_k=30` gives each question a wide slice of that layer to reason over.

### Stage 3: Write the Research Plan

```python theme={null}
    research_questions = {
        "vendor_conversations": [
            "What are the laptops that are discussed, together with their vendors?",
            "What pricing was offered by each vendor before and after discounts?",
            "What were the delivery time estimates for each product?",
        ],
        "purchase_history": [
            "Which vendors have we worked with in the past?",
            "What were the satisfaction ratings for each vendor?",
            "Were there any complaints or red flags associated with specific vendors?",
        ],
        "procurement_policies": [
            "What are our company’s bulk discount requirements?",
            "What is the maximum acceptable delivery time for non-critical items?",
            "What is the minimum vendor rating for new contracts?",
        ],
    }
```

The research plan is a dictionary keyed by category: three questions per memory layer, each one asked only where its answer lives. Offers and delivery estimates come from the vendor conversations, past performance from the purchase history, and the thresholds a vendor must clear from the policy document.

### Stage 4: Run the Research Loop

```python theme={null}
    for category, questions in research_questions.items():
        print(f"Category: {category}")
        research_notes[category] = []
        for q in questions:
            print(f"Question: \n{q}")
            results = await procurement_system.search_memory(q, search_categories=[category])
            top_answer = results[category][0]
            print(f"Answer: \n{top_answer}\n")
            research_notes[category].append({"question": q, "answer": top_answer})
```

Nine scoped recalls run in sequence, and the top answer of each is kept alongside the question that produced it. This is the agent's research phase: it gathers its own evidence before anything decides anything, and every note carries the question that justifies its presence.

### Stage 5: Compile the Evidence

```python theme={null}
    research_information = "\n\n".join(
        f"Q: {note['question']}\nA: {note['answer']}"
        for section in research_notes.values()
        for note in section
    )
```

The per-category notes are flattened into one plain-text block of Q/A pairs. Category boundaries mattered during retrieval — they are what kept each answer honest — but the decision step needs to weigh price against rating against policy, so the evidence is deliberately merged back together here.

### Stage 6: Decide from the Compiled Evidence

```python theme={null}
    final_decision = await LLMGateway.acreate_structured_output(
        text_input=research_information,
        system_prompt="""You are a procurement decision assistant. Use the provided QA pairs that were collected through a research phase. Recommend the best vendor,
         based on pricing, delivery, warranty, policy fit, and past performance. Be concise and justify your choice with evidence.
         """,
        response_model=str,
    )
```

One direct LLM call turns the compiled research into a recommendation. It does no retrieval of its own — the only facts it can cite are the ones the nine scoped recalls put in front of it, which is what makes the resulting justification traceable back to memory.

## Run It

```bash theme={null}
uv run python examples/demos/agentic/agentic_reasoning_procurement_example.py
```

The script first reports that it is setting up procurement memory data and that memory was successfully populated, which takes a few minutes while the four documents are ingested and cognified. It then prints each of the nine research steps in turn — the category, the question, and the answer recalled from that category — followed by the compiled research summary of all nine Q/A pairs. It ends with a `Final Decision:` section holding the recommended vendor and the reasoning behind it.

## Adapting It to Your Data

The shape here generalizes to any research-then-decide agent: pick the categories your decision actually depends on, tag each source with a node set at `remember()` time, and write one small set of questions per category. Two rules keep it working — a question is only asked in the category that can answer it, and the deciding call sees the compiled notes rather than the raw documents. Swapping in your own vendors, policies, or history files means editing the data folder and the `research_questions` dictionary, not the loop around them.

<Columns cols={2}>
  <Card title="NodeSets" icon="tags" href="/core-concepts/further-concepts/node-sets">
    How node-set labels are written and how `node_name` filters retrieval by them.
  </Card>

  <Card title="Recall" icon="search" href="/core-concepts/main-operations/recall">
    The retrieval operation behind every research question, and its other parameters.
  </Card>

  <Card title="Low-Level LLM" icon="cpu" href="/guides/low-level-llm">
    Calling `acreate_structured_output` directly, including Pydantic response models.
  </Card>

  <Card title="Inspecting Graph Completion Context" icon="route" href="/guides/graph-completion">
    What `GRAPH_COMPLETION` retrieves before an answer is generated.
  </Card>
</Columns>
