# 阶段钩子(Stages)
在消息处理管道的固定点位插入自己的逻辑。阶段比工具更底层:工具是模型主动调用的,阶段是流程经过时必然触发的。
### `StageContext.IsResponded`
```go
func (c *StageContext) IsResponded() bool
```
`plugin.go:172`
### `StageContext.Lock`
```go
func (c *StageContext) Lock()
```
**示例插件里的真实用法**
| 插件 | 位置 | 代码 |
|---|---|---|
| [`a2a`](../examples/index.md#a2a) | `example/a2a/plugin.go:158` | `p.sessMu.Lock()` |
| [`acp`](../examples/index.md#acp) | `example/acp/plugin.go:128` | `p.srvMu.Lock()` |
| [`browser`](../examples/index.md#browser) | `example/browser/plugin.go:427` | `p.mu.Lock()` |
| [`calendar`](../examples/index.md#calendar) | `example/calendar/plugin.go:433` | `p.mu.Lock()` |
`plugin.go:170`
### `StageContext.RLock`
```go
func (c *StageContext) RLock()
```
**示例插件里的真实用法**
| 插件 | 位置 | 代码 |
|---|---|---|
| [`acp`](../examples/index.md#acp) | `example/acp/plugin.go:267` | `p.mu.RLock()` |
| [`calendar`](../examples/index.md#calendar) | `example/calendar/plugin.go:649` | `p.mu.RLock()` |
| [`memo`](../examples/index.md#memo) | `example/memo/plugin.go:224` | `p.mu.RLock()` |
| [`qq`](../examples/index.md#qq) | `example/qq/plugin.go:1152` | `ctx.RLock()` |
`plugin.go:168`
### `StageContext.RUnlock`
```go
func (c *StageContext) RUnlock()
```
**示例插件里的真实用法**
| 插件 | 位置 | 代码 |
|---|---|---|
| [`acp`](../examples/index.md#acp) | `example/acp/plugin.go:273` | `p.mu.RUnlock()` |
| [`calendar`](../examples/index.md#calendar) | `example/calendar/plugin.go:650` | `defer p.mu.RUnlock()` |
| [`memo`](../examples/index.md#memo) | `example/memo/plugin.go:229` | `p.mu.RUnlock()` |
| [`qq`](../examples/index.md#qq) | `example/qq/plugin.go:1155` | `ctx.RUnlock()` |
`plugin.go:169`
### `PluginSDK.RegisterStage`
```go
func (s *PluginSDK) RegisterStage(stage Stage, handler StageHandler, scope ...StageScope)
```
RegisterStage registers a handler for a pipeline stage.
scope: StageScopeGlobal (default) — receives all stage events.
StageScopeOwnTools — only before_toolcall/after_toolcall for this plugin's tools.
**示例插件里的真实用法**
| 插件 | 位置 | 代码 |
|---|---|---|
| [`memo`](../examples/index.md#memo) | `example/memo/plugin.go:152` | `s.RegisterStage(sdk.StagePreAction, p.stagePreAction)` |
| [`qq`](../examples/index.md#qq) | `example/qq/plugin.go:719` | `s.RegisterStage(sdk.StageOnInput, p.onInputAuthContext, sdk.StageScopeGlobal)` |
| [`sanitizer`](../examples/index.md#sanitizer) | `example/sanitizer/plugin.go:52` | `s.RegisterStage(sdk.StageOnInput, func(ctx *sdk.StageContext) error {` |
| [`weather`](../examples/index.md#weather) | `example/weather/plugin.go:94` | `s.RegisterStage(sdk.StageAfterToolcall, func(ctx *sdk.StageContext) error {` |
`plugin.go:467`
### `Stage`
```go
type Stage string
```
Stage represents a point in the message processing pipeline.
`plugin.go:26`
### `StageContext`
```go
type StageContext struct { mu sync.RWMutex RawMessage string UserID string GroupID string ContextMsgs []map[string]interface{} L …
```
StageContext provides context for stage handlers.
`plugin.go:148`
### `StageHandler`
```go
type StageHandler func(ctx *StageContext) error
```
StageHandler is a function that handles a pipeline stage event.
`plugin.go:23`
### `StageRegistrar`
```go
type StageRegistrar func(stage Stage, handler StageHandler)
```
StageRegistrar registers a stage handler.
`plugin.go:308`
### `StageScope`
```go
type StageScope int
```
StageScope controls which events a stage handler receives.
`plugin.go:294`
### `StageContext.Unlock`
```go
func (c *StageContext) Unlock()
```
**示例插件里的真实用法**
| 插件 | 位置 | 代码 |
|---|---|---|
| [`a2a`](../examples/index.md#a2a) | `example/a2a/plugin.go:164` | `p.sessMu.Unlock()` |
| [`acp`](../examples/index.md#acp) | `example/acp/plugin.go:129` | `defer p.srvMu.Unlock()` |
| [`browser`](../examples/index.md#browser) | `example/browser/plugin.go:432` | `p.mu.Unlock()` |
| [`calendar`](../examples/index.md#calendar) | `example/calendar/plugin.go:523` | `p.mu.Unlock()` |
`plugin.go:171`