中间件:Agentic请求响应拦截器
引言:AI Agent开发中的拦截器痛点
在构建AI Agent应用时,你是否遇到过这些问题?
- 需要对所有API请求进行统一的认证处理
- 想要监控和分析每个AI函数的调用性能
- 需要在请求失败时实现智能重试机制
- 希望统一处理错误日志和监控指标
- 需要对敏感数据进行自动脱敏处理
Agentic框架通过强大的中间件系统,为开发者提供了完整的请求响应拦截解决方案。本文将深入解析Agentic的拦截器机制,帮助你构建更健壮、可观测的AI应用。
Agentic中间件架构解析
核心拦截点设计
Agentic基于Ky HTTP客户端构建,提供了两个关键的拦截钩子:
拦截器类型定义
// 请求前拦截器
type BeforeRequestHook = (request: Request) => Request | Response | void
// 响应后拦截器
type AfterResponseHook = (
request: Request,
options: NormalizedOptions,
response: Response
) => Response | void
实战:构建自定义拦截器
1. 认证令牌自动注入
import { KyInstance } from 'ky'
function createAuthInterceptor(apiKey: string) {
return (request: Request) => {
const url = new URL(request.url)
if (url.hostname.includes('api.weather.com')) {
const newUrl = new URL(request.url)
newUrl.searchParams.set('key', apiKey)
return new Request(newUrl.toString(), request)
}
return request
}
}
// 使用示例
const weatherClient = new WeatherClient().extend({
hooks: {
beforeRequest: [createAuthInterceptor(process.env.WEATHER_API_KEY)]
}
})
2. 性能监控中间件
interface PerformanceMetrics {
functionName: string
duration: number
status: 'success' | 'error'
timestamp: Date
}
function createPerformanceMonitor(
metricsCollector: (metrics: PerformanceMetrics) => void
) {
return {
beforeRequest: [(request: Request) => {
request.headers.set('x-start-time', Date.now().toString())
return request
}],
afterResponse: [(request: Request, options: any, response: Response) => {
const startTime = parseInt(request.headers.get('x-start-time') || '0')
const duration = Date.now() - startTime
metricsCollector({
functionName: new URL(request.url).pathname.split('/').pop() || 'unknown',
duration,
status: response.ok ? 'success' : 'error',
timestamp: new Date()
})
return response
}]
}
}
3. 智能重试机制
function createRetryInterceptor(
maxRetries: number = 3,
backoffMs: number = 1000
) {
return async (request: Request, options: any, response: Response) => {
if (response.status >= 500 && maxRetries > 0) {
await new Promise(resolve => setTimeout(resolve, backoffMs))
return fetch(request) // 重新发起请求
}
return response
}
}
高级拦截模式
组合式拦截器
function composeInterceptors(...interceptors: Array<{
beforeRequest?: BeforeRequestHook[]
afterResponse?: AfterResponseHook[]
}>) {
return {
beforeRequest: interceptors.flatMap(i => i.beforeRequest || []),
afterResponse: interceptors.flatMap(i => i.afterResponse || [])
}
}
// 组合多个拦截器
const combinedInterceptors = composeInterceptors(
createAuthInterceptor(API_KEY),
createPerformanceMonitor(console.log),
{ afterResponse: [createRetryInterceptor()] }
)
条件拦截器
function createConditionalInterceptor(
condition: (request: Request) => boolean,
interceptor: BeforeRequestHook | AfterResponseHook
) {
return (request: Request, options?: any, response?: Response) => {
if (!condition(request)) {
return response ? response : request
}
if (response) {
return (interceptor as AfterResponseHook)(request, options, response)
} else {
return (interceptor as BeforeRequestHook)(request)
}
}
}
企业级应用场景
1. 分布式追踪
function createTracingInterceptor() {
return {
beforeRequest: [(request: Request) => {
const traceId = generateTraceId()
request.headers.set('x-trace-id', traceId)
request.headers.set('x-span-id', generateSpanId())
return request
}],
afterResponse: [(request: Request, options: any, response: Response) => {
const traceId = request.headers.get('x-trace-id')
logTraceCompletion(traceId, response.status)
return response
}]
}
}
2. 数据脱敏与合规
function createDataMaskingInterceptor() {
return {
afterResponse: [async (request: Request, options: any, response: Response) => {
if (response.headers.get('content-type')?.includes('application/json')) {
const data = await response.json()
const maskedData = maskSensitiveFields(data)
return new Response(JSON.stringify(maskedData), response)
}
return response
}]
}
}
3. 速率限制与配额管理
class RateLimiter {
private requests = new Map<string, number[]>()
checkRateLimit(apiKey: string, maxRequests: number, timeWindowMs: number): boolean {
const now = Date.now()
const userRequests = this.requests.get(apiKey) || []
const recentRequests = userRequests.filter(time => now - time < timeWindowMs)
if (recentRequests.length >= maxRequests) {
return false
}
recentRequests.push(now)
this.requests.set(apiKey, recentRequests)
return true
}
}
function createRateLimitInterceptor(limiter: RateLimiter) {
return {
beforeRequest: [(request: Request) => {
const apiKey = extractApiKey(request)
if (!limiter.checkRateLimit(apiKey, 100, 60000)) {
throw new Error('Rate limit exceeded')
}
return request
}]
}
}
性能优化最佳实践
拦截器执行效率
// 高效的条件检查
function createOptimizedInterceptor() {
const skipPaths = new Set(['/health', '/metrics'])
return {
beforeRequest: [(request: Request) => {
const url = new URL(request.url)
if (skipPaths.has(url.pathname)) {
return request // 快速路径
}
// 复杂的处理逻辑
return processRequest(request)
}]
}
}
内存管理
// 避免内存泄漏的拦截器
function createMemorySafeInterceptor() {
const cache = new WeakMap<Request, any>()
return {
beforeRequest: [(request: Request) => {
// 使用WeakMap避免内存泄漏
cache.set(request, { timestamp: Date.now() })
return request
}],
afterResponse: [(request: Request) => {
cache.delete(request) // 及时清理
return response
}]
}
}
测试策略
单元测试拦截器
import { mockKyInstance } from '@agentic/core'
describe('Auth Interceptor', () => {
it('should add API key to weather requests', async () => {
const interceptor = createAuthInterceptor('test-key')
const mockKy = mockKyInstance(ky, {
beforeRequest: [interceptor]
})
const response = await mockKy.get('https://api.weather.com/v1/forecast')
const requestData = await response.json()
expect(requestData.url).toContain('key=test-key')
})
})
集成测试
describe('Performance Monitor', () => {
it('should collect metrics for successful requests', async () => {
const metrics: PerformanceMetrics[] = []
const monitor = createPerformanceMonitor(m => metrics.push(m))
const client = new WeatherClient().extend({
hooks: monitor
})
await client.getCurrentWeather({ q: 'San Francisco' })
expect(metrics).toHaveLength(1)
expect(metrics[0].status).toBe('success')
})
})
故障排除与调试
常见问题解决方案
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 拦截器未执行 | Ky实例未正确扩展 | 确保使用.extend()方法 |
| 内存泄漏 | 拦截器中持有请求引用 | 使用WeakMap存储临时数据 |
| 性能下降 | 拦截器逻辑过于复杂 | 优化条件判断,使用缓存 |
| 类型错误 | 拦截器返回值类型错误 | 严格遵循Hook类型定义 |
调试技巧
function createDebugInterceptor() {
return {
beforeRequest: [(request: Request) => {
console.log('Request:', request.method, request.url)
return request
}],
afterResponse: [(request: Request, options: any, response: Response) => {
console.log('Response:', response.status, response.statusText)
return response
}]
}
}
总结与展望
Agentic的中间件系统为AI应用开发提供了强大的拦截器能力,通过beforeRequest和afterResponse两个关键钩子,开发者可以实现:
- 统一的认证管理 - 自动处理API密钥和令牌
- 完整的可观测性 - 监控性能、错误率和调用链
- 智能的错误处理 - 重试机制、降级策略
- 数据合规保障 - 脱敏、审计日志记录
- 资源管理 - 速率限制、配额控制
随着AI应用的复杂度不断增加,良好的拦截器设计将成为构建可靠、可维护系统的关键因素。Agentic提供的中间件架构不仅解决了当前的技术痛点,更为未来的扩展和演进奠定了坚实基础。
提示:在实际项目中,建议根据具体需求选择合适的拦截器组合,避免过度设计。始终遵循"单一职责原则",让每个拦截器只关注一个特定的横切关注点。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



