Skip to content

Commit f2b9d07

Browse files
Update AGENTS.md
1 parent b8295f3 commit f2b9d07

File tree

1 file changed

+5
-12
lines changed

1 file changed

+5
-12
lines changed

AGENTS.md

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -107,30 +107,23 @@ slack_bolt/listener/async_listener.py # async
107107

108108
### Prefer the Middleware Pattern
109109

110-
Middleware is the project's preferred approach for cross-cutting concerns. Before adding logic to individual listeners or utility functions, consider whether it belongs in the middleware chain.
110+
Middleware is the project's preferred approach for cross-cutting concerns. Before adding logic to individual listeners or utility functions, consider whether it belongs as a built-in middleware in the framework.
111111

112-
**When to use middleware:**
112+
**When to add built-in middleware:**
113113

114114
- Cross-cutting concerns that apply to many or all requests (logging, metrics, observability)
115115
- Request validation, transformation, or enrichment
116116
- Authorization extensions beyond the built-in `SingleTeamAuthorization`/`MultiTeamsAuthorization`
117117
- Feature-level request handling (the `Assistant` middleware in `slack_bolt/middleware/assistant/assistant.py` is the canonical example -- it intercepts assistant thread events and dispatches them to registered sub-listeners)
118118

119-
**How to implement middleware:**
119+
**How to add built-in middleware:**
120120

121121
1. Subclass `Middleware` (sync) and implement `process(self, *, req, resp, next)`. Call `next()` to continue the chain.
122122
2. Subclass `AsyncMiddleware` (async) and implement `async_process(self, *, req, resp, next)`. Call `await next()` to continue.
123123
3. Export from `slack_bolt/middleware/__init__.py` (sync) and `slack_bolt/middleware/async_builtins.py` (async).
124-
4. Register via `App(middleware=[...])` or the `@app.middleware` decorator.
124+
4. Register the middleware in `App.__init__()` (`slack_bolt/app/app.py`) and `AsyncApp.__init__()` (`slack_bolt/app/async_app.py`) where the default middleware chain is assembled.
125125

126-
**Simple example using the decorator:**
127-
128-
```python
129-
@app.middleware
130-
def log_request(logger, body, next):
131-
logger.debug(f"Incoming request: {body.get('type')}")
132-
return next()
133-
```
126+
**Canonical example:** `AttachingFunctionToken` (`slack_bolt/middleware/attaching_function_token/`) is a good small middleware to follow -- it has a clean sync/async pair, a focused `process()` method, and is properly exported and registered in the app's middleware chain.
134127

135128
### Single Runtime Dependency Rule
136129

0 commit comments

Comments
 (0)