> This page is for Server SDKs.

> Fetch clean Markdown by appending `.md` to any page URL under https://signalwire.com/docs or requesting it with the HTTP header `Accept: text/markdown`. The root index at https://signalwire.com/docs/llms.txt lists the available documentation indexes.

# addPerCallConfig

> Register a per-request configuration callback without replacing callbacks already set.

[ref-agentbase]: /docs/server-sdks/reference/typescript/agents/agent-base

[set-dynamic-config-callback]: /docs/server-sdks/reference/typescript/agents/agent-base/set-dynamic-config-callback

[add-post-answer-verb]: /docs/server-sdks/reference/typescript/agents/agent-base/add-post-answer-verb

[clear-post-answer-verbs]: /docs/server-sdks/reference/typescript/agents/agent-base/clear-post-answer-verbs

Register a per-request configuration callback, keeping any already registered.
Same signature and contract as
[`setDynamicConfigCallback()`][set-dynamic-config-callback], except that
callbacks accumulate instead of replacing each other. They run in registration
order on the same per-request copy of the agent, so a later callback sees what
an earlier one configured.

Prefer this form when composing. A base class and a subclass, or an agent and a
helper, can each register what they own without knowing about the other.
Calling `setDynamicConfigCallback()` afterwards replaces every callback
registered so far.

Callbacks run for every request of a call: the SWML fetch, each SWAIG function
call, and the summary delivery. Only the SWML fetch carries the caller's data,
such as user variables, so verify the caller there, remember the `call_id`, and
check it on later requests.

## Parameters

**`cb`** `DynamicConfigCallback` — required

A function with the signature
`(queryParams: Record<string, string>, bodyParams: SwmlRequestData, headers: Record<string, string>, agent: AgentBase) => void | Promise<void>`.
`agent` is the per-request copy. Configure that object, never the agent
itself, or the configuration leaks across callers.

---

## Returns

[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining.

## Rejecting a call

A callback can't refuse the request, but it can decide what the call does.
Build the agent to fail closed: add a goodbye with
[`addPostAnswerVerb('play', …)`][add-post-answer-verb] and
`addPostAnswerVerb('hangup', {})`, and no tools, so a call hears the message
and hangs up before the `ai` verb runs. For a call the callback accepts, add the
tools to the copy and call [`clearPostAnswerVerbs()`][clear-post-answer-verbs]
last.

A callback that throws is logged, and the copy is rendered as it stands, so a
failure before that last step leaves the goodbye in place. A throwing callback
also stops the ones after it without restoring verbs an earlier one cleared, so
the callback that clears them must be registered last.

## Example

```typescript {6-14}
import { AgentBase } from '@signalwire/sdk';

const agent = new AgentBase({ name: 'dispatch', route: '/dispatch' });
agent.setPromptText('You are Ada, the dispatcher for Bayview Taxi.');

agent.addPerCallConfig((queryParams, bodyParams, headers, copy) => {
  if (queryParams.lang === 'es') {
    copy.addLanguage({ name: 'Spanish', code: 'es-MX', voice: 'rime.marsh' });
  }
});

agent.addPerCallConfig((queryParams, bodyParams, headers, copy) => {
  copy.setGlobalData({ tenant: queryParams.tenant ?? 'default' });
});

await agent.serve();
```