Files
Hayden Bleasel 30698ed6d8 Adapters (#204)
* Initial marketplace draft

* Update language

* Add logos to cards

* Redesign cards

* Update adapter-card.tsx

* Update adapter-card.tsx

* Migrate marketplace to adapters

* Update meta.json

* Split adapters into new three groups

* Add iMessage

* Move adapter docs to READMEs

* Cleanup docs

* Add more logos, implement shadcn ui components

* Update adapters.json

* Add Streamdown

* Fetch vercel readmes from workspace

* Update readme-content.tsx

* Upgrade Streamdown

* Update global.css

* Update adapters.json

* Update adapters.json

* Add links to docs

* List upcoming official adapters

* Update adapters.json

* Fix adapters links

* Fix typo

* Misc fixes

* Update adapters.json

* Update adapters.json

* Migrate new info

* Update pnpm-lock.yaml

* Update adapter-card.tsx

* Add postgres to adapters page

* Update adapter-card.tsx

* Migrate postgres docs

* Add pg to valid README imports

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Move feature matrices from docs to package READMEs

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Remove packages tables from adapter/state docs

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Genericize adapter/state doc descriptions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: improve adapters page accessibility and empty state handling

* Add custom adapter building section to SKILL.md

* Use currentColor for GitHub, Linear, and Memory icons

* Use GitHub API for README fetch, add heading to fallback state

Use the GitHub REST API instead of raw.githubusercontent.com to
automatically resolve the repo's default branch, so community
adapters using master or other branch names work correctly.

* Update adapters-grid.tsx

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com>
2026-03-09 16:09:42 -07:00

45 lines
1.9 KiB
Plaintext

---
title: State Adapters
description: Pluggable state adapters for thread subscriptions, distributed locking, and caching.
type: overview
prerequisites:
- /docs/getting-started
---
State adapters handle persistent storage for thread subscriptions, distributed locks (to prevent duplicate processing), and caching. You must provide a state adapter when creating a `Chat` instance. Browse all available state adapters on the [Adapters](/adapters) page.
## What state adapters manage
### Thread subscriptions
When your bot calls `thread.subscribe()`, the state adapter persists that subscription. On subsequent webhooks, the SDK checks subscriptions to route messages to `onSubscribedMessage` handlers. With a production adapter, subscriptions survive restarts and work across multiple instances.
### Distributed locking
When a webhook arrives, the SDK acquires a lock on the thread to prevent duplicate processing. This is critical for serverless deployments where multiple instances may receive the same event.
By default, if a lock is already held, the incoming message is dropped with a `LockError`. For long-running handlers (e.g. AI agent streaming), you can configure `onLockConflict: 'force'` to force-release the existing lock and allow the new message through:
```typescript
const chat = new Chat({
userName: 'my-bot',
adapters: { slack },
state: createRedisState(),
onLockConflict: 'force',
});
```
You can also pass a callback for custom logic:
```typescript
onLockConflict: (threadId, message) => {
return message.text.includes('stop') ? 'force' : 'drop';
}
```
Note that force-releasing a lock does not cancel the previous handler — it continues running. Only the lock is released, so two handlers may briefly run concurrently on the same thread.
### Caching
State adapters provide key-value storage with TTL for thread state (`thread.setState()`), message deduplication, and other internal caching.