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

# harnest_threadify

> Public Python signatures, fields, and methods.

[All Python modules](https://usefused.com/docs/harnest/reference/api/overview.md) · [Import and compatibility guidance](https://usefused.com/docs/harnest/build/python-imports.md)

## Exports

| Name | Kind |
| - | - |
| [`BusinessFilter`](#businessfilter) | Class |
| [`Threadify`](#threadify) | Class |

## BusinessFilter

Select authored steps and scalar attributes; discard all events and links.

```python theme={null}
BusinessFilter(
    spans: tuple[str, ...] = ('harnest.request', 'harnest.decision.evaluate', 'business.*'),
    attributes: tuple[str, ...] = (),
    max_string_length: int = 256,
) -> None
```

Fields (`—` means no declared default):

| Field | Type | Default |
| - | - | - |
| `spans` | `tuple[str, ...]` | `('harnest.request', 'harnest.decision.evaluate', 'business.*')` |
| `attributes` | `tuple[str, ...]` | `()` |
| `max_string_length` | `int` | `256` |

> [accordion] Parameters and example
>
> | Parameter | Type | Default |
> | - | - | - |
> | `spans` | `tuple[str, ...]` | `('harnest.request', 'harnest.decision.evaluate', 'business.*')` |
> | `attributes` | `tuple[str, ...]` | `()` |
> | `max_string_length` | `int` | `256` |
>
> ```python theme={null}
> from harnest_threadify import BusinessFilter
>
> business_filter = BusinessFilter()
> ```

### BusinessFilter.sanitize

```python theme={null}
BusinessFilter.sanitize(span: opentelemetry.sdk.trace.ReadableSpan, *, service_name: str) -> opentelemetry.sdk.trace.ReadableSpan | None
```

Build a separate span so filtering cannot affect another destination.

> [accordion] Parameters and example
>
> | Parameter | Type | Default |
> | - | - | - |
> | `span` | `opentelemetry.sdk.trace.ReadableSpan` | Required |
> | `service_name` | `str` | Required |
>
> ```python theme={null}
> from harnest_threadify import BusinessFilter
>
> business_filter: BusinessFilter
> result = business_filter.sanitize(span=..., service_name=...)
> ```

## Threadify

Opt-in SDK/OTLP integration, configured without import-time credentials or I/O.

```python theme={null}
Threadify(
    *,
    service_name: str,
    api_key_env: str = 'THREADIFY_API_KEY',
    filter: BusinessFilter | None = None,
    business_tools: tuple[str, ...] = (),
    otlp_endpoint: str | None = None,
    otlp_headers: Mapping[str, str] | None = None,
    connection_options: Mapping[str, Any] | None = None,
    timeout: float = 10.0,
    max_sessions: int = 10000,
) -> None
```

> [accordion] Parameters and example
>
> | Parameter | Type | Default |
> | - | - | - |
> | `service_name` | `str` | Required |
> | `api_key_env` | `str` | `'THREADIFY_API_KEY'` |
> | `filter` | `BusinessFilter \| None` | `None` |
> | `business_tools` | `tuple[str, ...]` | `()` |
> | `otlp_endpoint` | `str \| None` | `None` |
> | `otlp_headers` | `Mapping[str, str] \| None` | `None` |
> | `connection_options` | `Mapping[str, Any] \| None` | `None` |
> | `timeout` | `float` | `10.0` |
> | `max_sessions` | `int` | `10000` |
>
> ```python theme={null}
> from harnest_threadify import Threadify
>
> threadify = Threadify(service_name=...)
> ```

### Threadify.native\_class

Expose the actual SDK factory only when explicitly requested.

> [accordion] Example
>
> ```python theme={null}
> from harnest_threadify import Threadify
>
> threadify: Threadify
> value = threadify.native_class
> ```

### Threadify.native

Return the native connection on the application's async event loop.

> [accordion] Example
>
> ```python theme={null}
> from harnest_threadify import Threadify
>
> threadify: Threadify
> value = threadify.native
> ```

### Threadify.telemetry\_exporter

```python theme={null}
Threadify.telemetry_exporter() -> TelemetryExporter
```

Construct the filtered destination once; Harnest owns batch processing.

> [accordion] Example
>
> ```python theme={null}
> from harnest_threadify import Threadify
>
> threadify: Threadify
> exporter = threadify.telemetry_exporter()
> ```

### Threadify.**aenter**

```python theme={null}
async Threadify.__aenter__() -> Threadify
```

Connect only during runtime startup and install session correlation.

> [accordion] Example
>
> ```python theme={null}
> from harnest_threadify import Threadify
>
> threadify: Threadify
> async with threadify:
>     ...
> ```

### Threadify.**aexit**

```python theme={null}
async Threadify.__aexit__(*exc: Any) -> None
```

Flush while the SDK loop is alive, then release the connection.

> [accordion] Parameters and example
>
> | Parameter | Type | Default |
> | - | - | - |
> | `*exc` | `Any` | Optional |
>
> ```python theme={null}
> from harnest_threadify import Threadify
>
> threadify: Threadify
> async with threadify:
>     ...
> ```

### Threadify.session

```python theme={null}
async Threadify.session(*, user_id: str, session_id: str) -> ThreadInstance | None
```

Reuse a session thread and recover its durable reference after restart.

> [accordion] Parameters and example
>
> | Parameter | Type | Default |
> | - | - | - |
> | `user_id` | `str` | Required |
> | `session_id` | `str` | Required |
>
> ```python theme={null}
> from harnest_threadify import Threadify
>
> threadify: Threadify
> result = await threadify.session(user_id=..., session_id=...)
> ```

### Threadify.annotate

```python theme={null}
Threadify.annotate(span: Span, user_id: str, session_id: str) -> None
```

Attach only an already verified session binding to a recording span.

> [accordion] Parameters and example
>
> | Parameter | Type | Default |
> | - | - | - |
> | `span` | `Span` | Required |
> | `user_id` | `str` | Required |
> | `session_id` | `str` | Required |
>
> ```python theme={null}
> from harnest_threadify import Threadify
>
> threadify: Threadify
> threadify.annotate(span=..., user_id=..., session_id=...)
> ```

### Threadify.session\_created

```python theme={null}
async Threadify.session_created(info: AgentInfo, session: SessionRecord) -> None
```

Link a committed new session without forwarding state or metadata.

> [accordion] Parameters and example
>
> | Parameter | Type | Default |
> | - | - | - |
> | `info` | `AgentInfo` | Required |
> | `session` | `SessionRecord` | Required |
>
> ```python theme={null}
> from harnest_threadify import Threadify
>
> threadify: Threadify
> await threadify.session_created(info=..., session=...)
> ```

### Threadify.before\_invocation

```python theme={null}
async Threadify.before_invocation(lifecycle_context: LifecycleContext, request: InvocationRequest) -> Next[Any]
```

Recover sessions opened before integration and link every agent turn.

> [accordion] Parameters and example
>
> | Parameter | Type | Default |
> | - | - | - |
> | `lifecycle_context` | `LifecycleContext` | Required |
> | `request` | `InvocationRequest` | Required |
>
> ```python theme={null}
> from harnest_threadify import Threadify
>
> threadify: Threadify
> result = await threadify.before_invocation(lifecycle_context=..., request=...)
> ```

### Threadify.request\_scope

```python theme={null}
Threadify.request_scope(http_context: HTTPLifecycleContext, request: HTTPCallRequest) -> AsyncIterator[None]
```

Keep one payload-free business request span alive through streaming.

> [accordion] Parameters and example
>
> | Parameter | Type | Default |
> | - | - | - |
> | `http_context` | `HTTPLifecycleContext` | Required |
> | `request` | `HTTPCallRequest` | Required |
>
> ```python theme={null}
> from harnest_threadify import Threadify
>
> threadify: Threadify
> async with threadify.request_scope(http_context=..., request=...):
>     ...
> ```

### Threadify.after\_http

```python theme={null}
Threadify.after_http(http_context: HTTPLifecycleContext, response: HTTPResponseHead) -> Next[Any]
```

Capture handled HTTP failures without exporting URL paths or headers.

> [accordion] Parameters and example
>
> | Parameter | Type | Default |
> | - | - | - |
> | `http_context` | `HTTPLifecycleContext` | Required |
> | `response` | `HTTPResponseHead` | Required |
>
> ```python theme={null}
> from harnest_threadify import Threadify
>
> threadify: Threadify
> result = threadify.after_http(http_context=..., response=...)
> ```

### Threadify.current\_thread

```python theme={null}
async Threadify.current_thread() -> ThreadInstance | None
```

Expose the native thread for the active, owner-checked invocation.

> [accordion] Example
>
> ```python theme={null}
> from harnest_threadify import Threadify
>
> threadify: Threadify
> result = await threadify.current_thread()
> ```

### Threadify.workflow

```python theme={null}
async Threadify.workflow(
    key: str,
    *,
    contract: str,
    role: str,
    label: str | None = None,
    refs: Mapping[str, str] | None = None,
) -> ThreadInstance
```

Open a shared contract thread for an application-verified business key.

This path is strict: an unavailable Engine must stop a governed action,
even though passive session telemetry remains best effort.

> [accordion] Parameters and example
>
> | Parameter | Type | Default |
> | - | - | - |
> | `key` | `str` | Required |
> | `contract` | `str` | Required |
> | `role` | `str` | Required |
> | `label` | `str \| None` | `None` |
> | `refs` | `Mapping[str, str] \| None` | `None` |
>
> ```python theme={null}
> from harnest_threadify import Threadify
>
> threadify: Threadify
> result = await threadify.workflow(key=..., contract=..., role=...)
> ```

### Threadify.join\_workflow

```python theme={null}
async Threadify.join_workflow(thread_id: str, *, role: str) -> ThreadInstance
```

Join an authorized business thread whose ID came from a trusted service.

> [accordion] Parameters and example
>
> | Parameter | Type | Default |
> | - | - | - |
> | `thread_id` | `str` | Required |
> | `role` | `str` | Required |
>
> ```python theme={null}
> from harnest_threadify import Threadify
>
> threadify: Threadify
> result = await threadify.join_workflow(thread_id=..., role=...)
> ```

### Threadify.step

```python theme={null}
Threadify.step(name: str, *, attributes: Mapping[str, Any] | None = None) -> Iterator[Span]
```

Record an explicit business step with the destination's attribute policy.

> [accordion] Parameters and example
>
> | Parameter | Type | Default |
> | - | - | - |
> | `name` | `str` | Required |
> | `attributes` | `Mapping[str, Any] \| None` | `None` |
>
> ```python theme={null}
> from harnest_threadify import Threadify
>
> threadify: Threadify
> with threadify.step(name=...):
>     ...
> ```

### Threadify.tool\_completed

```python theme={null}
Threadify.tool_completed(active: Any, result: Any) -> Next[Any]
```

Record only named business tools, without arguments or return values.

> [accordion] Parameters and example
>
> | Parameter | Type | Default |
> | - | - | - |
> | `active` | `Any` | Required |
> | `result` | `Any` | Required |
>
> ```python theme={null}
> from harnest_threadify import Threadify
>
> threadify: Threadify
> result = threadify.tool_completed(active=..., result=...)
> ```

### Threadify.tool\_failed

```python theme={null}
Threadify.tool_failed(active: Any, error: BaseException) -> None
```

Record failure categories without exception text or framework internals.

> [accordion] Parameters and example
>
> | Parameter | Type | Default |
> | - | - | - |
> | `active` | `Any` | Required |
> | `error` | `BaseException` | Required |
>
> ```python theme={null}
> from harnest_threadify import Threadify
>
> threadify: Threadify
> threadify.tool_failed(active=..., error=...)
> ```

### Threadify.export\_spans

```python theme={null}
async Threadify.export_spans(spans: Sequence[ReadableSpan]) -> None
```

Translate sanitized spans using public SDK APIs and stable event keys.

> [accordion] Parameters and example
>
> | Parameter | Type | Default |
> | - | - | - |
> | `spans` | `Sequence[ReadableSpan]` | Required |
>
> ```python theme={null}
> from harnest_threadify import Threadify
>
> threadify: Threadify
> await threadify.export_spans(spans=...)
> ```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.