# Manage Interceptors - TypeScript SDK

Interceptors are SDK hooks that let you intercept inbound and outbound Temporal calls. You use them to apply shared
behavior across many calls, such as tracing and authorization, before calls reach the application code and after they return.
This is similar to middleware in other frameworks.

There are two main types of interceptors--inbound and outbound.

* Outbound interceptors wrap network calls, running before they reach the network and after they return.
* Inbound interceptors run after the network hop, wrapping application code and running before it starts and after it returns.

Those further break down into concrete Interceptor types--see below.

## How to implement interceptors in TypeScript 

Interceptors run as a chain.  Each interceptor wraps the entire inner call: your code runs before the call, invokes `next` to execute the rest of the chain, and then runs after the call completes. This means you can inspect or modify both the `input` and the result, handle errors, and perform side effects at either stage.

The TypeScript SDK comes with an optional interceptor package that adds tracing with
[OpenTelemetry](https://www.npmjs.com/package/@temporalio/interceptors-opentelemetry). See how to use it in the
[interceptors-opentelemetry](https://github.com/temporalio/samples-typescript/tree/main/interceptors-opentelemetry) code
sample.

- [WorkflowInboundCallsInterceptor](https://typescript.temporal.io/api/interfaces/workflow.WorkflowInboundCallsInterceptor/):
  Intercept Workflow inbound calls like execution, Signals, and Queries.
- [WorkflowOutboundCallsInterceptor](https://typescript.temporal.io/api/interfaces/workflow.WorkflowOutboundCallsInterceptor/):
  Intercept Workflow outbound calls to Temporal APIs like scheduling Activities and starting Timers.
- [ActivityInboundCallsInterceptor](https://typescript.temporal.io/api/interfaces/worker.ActivityInboundCallsInterceptor):
  Intercept inbound calls to an Activity (such as `execute`).
- [WorkflowClientInterceptor](https://typescript.temporal.io/api/interfaces/client.WorkflowClientInterceptor/):
  Intercept workflow-related methods of [`Client`](https://typescript.temporal.io/api/classes/client.Client/) and
  [`WorkflowHandle`](https://typescript.temporal.io/api/interfaces/client.WorkflowHandle) like starting or signaling a
  Workflow.
- [NexusInboundCallsInterceptor](https://typescript.temporal.io/api/interfaces/worker.NexusInboundCallsInterceptor):
  Intercept inbound Nexus Operation calls like `startOperation` and `cancelOperation`.
- [NexusOutboundCallsInterceptor](https://typescript.temporal.io/api/interfaces/worker.NexusOutboundCallsInterceptor):
  Intercept outbound calls from Nexus Operations, such as enriching log attributes and metric tags.

All interceptor methods are optional—it's up to the implementor to choose which methods to intercept.

## Interceptor examples

**Log start and completion of Activities**

```ts
import { ActivityInput, Next, WorkflowOutboundCallsInterceptor } from '@temporalio/workflow';

export class ActivityLogInterceptor implements WorkflowOutboundCallsInterceptor {
  constructor(public readonly workflowType: string) {}

  async scheduleActivity(
    input: ActivityInput,
    next: Next<WorkflowOutboundCallsInterceptor, 'scheduleActivity'>
  ): Promise<unknown> {
    console.log('Starting activity', { activityType: input.activityType });
    try {
      return await next(input);
    } finally {
      console.log('Completed activity', {
        workflow: this.workflowType,
        activityType: input.activityType,
      });
    }
  }
}
```

**Log Nexus Operations**

```ts
import type {
  NexusInboundCallsInterceptor,
  NexusStartOperationInput,
  NexusStartOperationOutput,
  Next,
} from '@temporalio/worker';

export class NexusOperationLogInterceptor implements NexusInboundCallsInterceptor {
  async startOperation(
    input: NexusStartOperationInput,
    next: Next<NexusInboundCallsInterceptor, 'startOperation'>
  ): Promise<NexusStartOperationOutput> {
    console.log('Starting Nexus operation', {
      service: input.ctx.service,
      operation: input.ctx.operation,
    });
    const output = await next(input);
    console.log('Nexus operation started', {
      service: input.ctx.service,
      operation: input.ctx.operation,
      async: output.result.isAsync,
    });
    return output;
  }
}
```

## Register an Interceptor 

Registering an interceptor means providing it to the SDK so Temporal can invoke it when matching Client or Worker calls occur. Once registered, it runs in the call path and can observe or modify request and response data.

### Register via a Plugin

If you're building a reusable library or want to bundle interceptors with other primitives, you can register them
through a [Plugin](/develop/plugins-guide#interceptors).

### Activity and client interceptors registration

- Activity interceptors are registered on Worker creation by passing an array of
  [ActivityInboundCallsInterceptor factory functions](https://typescript.temporal.io/api/interfaces/worker.ActivityInboundCallsInterceptorFactory)
  through [WorkerOptions](https://typescript.temporal.io/api/interfaces/worker.WorkerOptions#interceptors).

- Client interceptors are registered on `Client` construction by passing an array of
  [WorkflowClientInterceptor](https://typescript.temporal.io/api/interfaces/client.WorkflowClientInterceptor) via
  [ClientOptions.interceptors](https://typescript.temporal.io/api/interfaces/client.ClientOptions#interceptors).

### Workflow interceptors registration

Workflow interceptor registration is different from the other interceptors because they run in the Workflow isolate. To
register Workflow interceptors, export an `interceptors` function from a file located in the `workflows` directory and
provide the name of that file to the Worker on creation via
[WorkerOptions](https://typescript.temporal.io/api/interfaces/worker.WorkerOptions#interceptors).

At the time of construction, the Workflow context is already initialized for the current Workflow. You may call the
[`workflowInfo()`](https://typescript.temporal.io/api/namespaces/workflow#workflowinfo) function to access
Workflow-specific information from an interceptor.

`src/workflows/your-interceptors.ts`

```ts
import { workflowInfo } from '@temporalio/workflow';

export const interceptors = () => ({
  outbound: [new ActivityLogInterceptor(workflowInfo().workflowType)],
  inbound: [],
});
```

`src/worker/index.ts`

```ts
const worker = await Worker.create({
  workflowsPath: require.resolve('./workflows'),
  interceptors: {
    workflowModules: [require.resolve('./workflows/your-interceptors')],
  },
});
```

### Nexus interceptor registration

Nexus interceptors are registered on Worker creation via
[WorkerOptions](https://typescript.temporal.io/api/interfaces/worker.WorkerOptions#interceptors).
Pass an array of factory functions to `interceptors.nexus`.
Each factory receives an [`OperationContext`](https://typescript.temporal.io/api/classes/nexus.OperationContext) and returns an object with optional `inbound` and `outbound` interceptors.

`src/worker/index.ts`

```ts
import { NexusOperationLogInterceptor } from './nexus-interceptors';

const worker = await Worker.create({
  // ...
  nexusServices: [/* your Nexus services */],
  interceptors: {
    nexus: [
      (_ctx) => ({
        inbound: new NexusOperationLogInterceptor(),
      }),
    ],
  },
});
```
