---
title: "Query keys & invalidation"
description: "Use the query key factories to invalidate caches after mutations."
section: "Libraries"
group: "React"
---

# Query keys & invalidation

Every entity ships a key factory — `agentKeys`, `workflowKeys`, `fileKeys`, and so on — that your code should use instead of hardcoding key strings. The factory enforces a consistent cache shape and lets the event-stream hook invalidate automatically.

## Shape

```ts
agentKeys.all(); // ["agents"]                    invalidates every agent query
agentKeys.list(p); // ["agents", "list", params]  one specific list
agentKeys.detail(id); // ["agents", id]            one specific agent
agentKeys.functions(id); // ["agents", id, "functions"]   sub-resource
```

Mutation hooks already invalidate `<entity>Keys.all()` on success, so the default case is free.

## useInvalidate

For manual invalidation, use the `useInvalidate` helper. It accepts any number of query keys and avoids pulling TanStack Query into your component.

```tsx
import { agentKeys, functionKeys, useInvalidate } from "@aeontel/react";

function SyncAgentButton({ agentId }: { agentId: string }) {
  const invalidate = useInvalidate();
  return (
    <Button
      onClick={async () => {
        await doSync(agentId);
        invalidate(agentKeys.detail(agentId), functionKeys.all());
      }}
    >
      Sync functions
    </Button>
  );
}
```

## Invalidating from mutation callbacks

```tsx
import { useCreateAgent, agentKeys } from "@aeontel/react";
import { useQueryClient } from "@tanstack/react-query";

function NewAgentForm({ workspaceId }: { workspaceId: string }) {
  const qc = useQueryClient();
  const create = useCreateAgent({
    onSuccess: () => qc.invalidateQueries({ queryKey: agentKeys.all() }),
  });
  // ...
}
```

## Why factories matter

`useEventStream` routes incoming events (e.g. `agent.updated`) back to the right factory via an internal `ENTITY_TYPE_TO_QUERY_KEY` map. If you invent ad-hoc keys, they won't be invalidated when an event arrives — you'll see stale data in the UI until the next refetch interval. Always use the factory.
