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

# Context

> Scope the graph with CQL or a structured filter, preview it, and compile it into context.

A **scope** describes which entities you mean. You write it as a
[CQL string](/concepts/cql) (`cql`) or a **structured filter** (`filter`), preview
what it matches, then compile it into context your agents consume. The same scope
grammar drives ad-hoc preview, [slice](/sdk/slices) authoring, and compilation.

## Scope: CQL or a structured filter

Both express the same thing with **names, not UUIDs**. `cql` is canonical if you
pass both. New to CQL? Start with [the CQL page](/concepts/cql).

```ts theme={null}
// CQL string (terse)
{ cql: 'type:Company shape:"Account Intelligence" after:7d' }

// Structured filter (discoverable; the only form for property predicates)
{ filter: {
    types: ["Company"],
    shapes: ["Account Intelligence"],
    properties: [{ path: "stage", operator: "eq", value: "alpha" }],
    after: "2026-01-01",
} }
```

Membership tokens: `type:` (entity type names, union), `shape:` (one shape per
scope), `source:` (source file names), `source-shape:"file"->"shape"`, and
`after:` / `before:` (created-at bounds). Same-kind tokens union; different-kind
intersect.

### Relative dates

`after:` / `before:` accept absolute ISO (`YYYY-MM-DD`) or relative
expressions, resolved to absolute time server-side (UTC):

| Form                                   | Meaning                                   |
| -------------------------------------- | ----------------------------------------- |
| `last-week`, `last-month`, `last-year` | a week / month / year ago                 |
| `today`, `yesterday`, `now`            | start of today / yesterday / this instant |
| `7d`, `-7d`, `2w`, `12h`, `3mo`, `1y`  | N units ago (sign ignored; past-only)     |

### Honest warnings, never silent drops

Anything a scope can't express comes back in `scope_warnings` instead of being
dropped silently:

* `edge:`, `agent:`, `sort:`, and free text are query/ranking concerns, not
  membership. They are ignored with a warning.
* A second `shape:`, an unresolved shape/source name, or a malformed date each
  produce a warning.
* Property predicates and `gt` / `lt` operators are available only on the
  structured `filter`, not in the CQL string.

## Preview a scope

Preview resolves a scope to a `matched` count plus warnings, without saving. It is
fast author-time feedback.

```ts theme={null}
const preview = await pb.context.preview({ cql: "type:Company after:7d" });
// { matched: 4, scope_warnings: [], counts: { entities: 4, ... } }
```

## Compile a scope or slice

Compile turns a scope, or a saved [slice](/sdk/slices), into a `CompiledContext`
payload your agents consume.

```ts theme={null}
const compiled = await pb.context.compile({ slice_id: sliceId });
// or ad-hoc:
const adhoc = await pb.context.compile({ cql: "type:Concept type:Metric" });
```

When your key is scoped to a single project, the project is implicit. Otherwise
pass `project_id` (or the `X-Penumbra-Project` header).

## Method reference

| Method                       | REST                       | Description                                        |
| ---------------------------- | -------------------------- | -------------------------------------------------- |
| `pb.context.preview(scope)`  | `POST /v1/context/preview` | Resolve a scope to a matched count + warnings.     |
| `pb.context.compile(scope)`  | `POST /v1/context/compile` | Compile a scope (or `slice_id`) into context.      |
| `pb.context.discover(input)` | `GET /v1/context/discover` | Find candidate types/sources/slices to scope from. |

## Related

<Columns cols={2}>
  <Card title="Slices" icon="bookmark" href="/sdk/slices">
    Save a scope under a name and reuse it.
  </Card>

  <Card title="CQL" icon="terminal" href="/concepts/cql">
    The full scope-string grammar.
  </Card>
</Columns>
