# Naming steps: set_span_name (/docs/sdk/set-span-name)



By default an LLM span is named after the model. When one call is really "the summarizer" or "the
router," name it — the label shows up in traces and can be matched by rules.

`set_span_name` labels the **next** LLM span only. It's consumed once, then cleared; the call after
that goes back to the model name.

```python
import token_police as tp

tp.set_span_name("summarize")
summary = client.chat.completions.create(...)   # this span is "summarize"

client.chat.completions.create(...)             # back to the model name
```

Node:

```typescript
import * as tp from "token-police";

tp.setSpanName("summarize");
await client.chat.completions.create(/* ... */);
```

## The Node scope-local gotcha [#the-node-scope-local-gotcha]

In **Python**, `set_span_name` works anywhere — it's stored on a context variable.

In **Node**, `setSpanName` is **scope-local**: it only takes effect inside a `session` / `agent` /
`chain` / `workflow` scope. Call it at the top level, outside any wrapper, and it's a **silent
no-op** — the span keeps its model name and nothing errors.

<Callout type="warn">
  Node: name your spans **inside** a wrapper. If `setSpanName` seems to do nothing, that call isn't
  inside a `session` / `agent` / `chain` / `workflow` — wrap the work first (see
  [Wrapping your app](/docs/sdk/wrapping)).
</Callout>

```typescript
// ✅ Node — inside a scope, the name sticks
await tp.workflow({ name: "report" }, async () => {
  tp.setSpanName("summarize");
  await client.chat.completions.create(/* ... */);
});
```

## Next [#next]

<Cards>
  <Card title="Wrapping your app" href="/docs/sdk/wrapping" description="Open the scope that makes setSpanName work in Node." />
</Cards>
