deepagents-architectur…
Guides architectural decisions for Deep Agents applications. Use when deciding between Deep Agents vs alternatives, choosing backend strategies, designing…
Idiomatic Go HTTP middleware patterns with context propagation, structured logging via slog, centralized error handling, and panic recovery. Use when writing middleware, adding request tracing, or implementing cross-cutting concerns.
$ npx -y skills add existential-birds/beagle --skill go-middleware --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/go-middlewareContext preview
The summary Claude sees to decide when to auto-load this skill.
Idiomatic Go HTTP middleware patterns with context propagation, structured logging via slog, centralized error handling, and panic recovery. Use when writing middleware, adding request tracing, or implementing cross-cutting concerns.
name: go-middleware description: Idiomatic Go HTTP middleware patterns with context propagation, structured logging via slog, centralized error handling, and panic recovery. Use when writing middleware, adding request tracing, or implementing cross-cutting concerns.
| Topic | Reference | |-------|-----------| | Context keys, request IDs, user metadata | [references/context-propagation.md](references/context-propagation.md) | | slog setup, logging middleware, child loggers | [references/structured-logging.md](references/structured-logging.md) | | AppHandler pattern, domain errors, recovery | [references/error-handling-middleware.md](references/error-handling-middleware.md) |
All middleware follows the standard `func(http.Handler) http.Handler` pattern. This is the composable building block for cross-cutting concerns in Go HTTP servers.
// Standard middleware signature
func RequestID(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
id := r.Header.Get("X-Request-ID")
if id == "" {
id = uuid.New().String()
}
ctx := context.WithValue(r.Context(), requestIDKey, id)
w.Header().Set("X-Request-ID", id)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
// Type-safe context keys
type contextKey string
const requestIDKey contextKey = "request_id"
func RequestIDFromContext(ctx context.Context) string {
id, _ := ctx.Value(requestIDKey).(string)
return id
}Key points:
Use `context.WithValue` for request-scoped data that crosses API boundaries (request IDs, authenticated users, tenant IDs). Always use typed keys to avoid collisions.
type contextKey string
const (
requestIDKey contextKey = "request_id"
userKey contextKey = "user"
)Provide typed helper functions for extraction:
func RequestIDFromContext(ctx context.Context) string {
id, _ := ctx.Value(requestIDKey).(string)
return id
}See [references/context-propagation.md](references/context-propagation.md) for user metadata patterns, downstream propagation, and timeouts.
Use `slog` (standard library, Go 1.21+) for structured logging in middleware. Wrap `http.ResponseWriter` to capture the status code.
func Logger(logger *slog.Logger) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
wrapped := &statusWriter{ResponseWriter: w, status: http.StatusOK}
next.ServeHTTP(wrapped, r)
logger.Info("request completed",
"method", r.Method,
"path", r.URL.Path,
"status", wrapped.status,
"duration_ms", time.Since(start).Milliseconds(),
"request_id", RequestIDFromContext(r.Context()),
)
})
}
}See [references/structured-logging.md](references/structured-logging.md) for JSON/text handler setup, log levels, and child loggers.
Define a custom handler type that returns `error` so handlers don't need to write error responses themselves:
type AppHandler func(w http.ResponseWriter, r *http.Request) error
func (fn AppHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if err := fn(w, r); err != nil {
handleError(w, r, err)
}
}Map domain errors to HTTP status codes in a single `handleError` function. Never leak internal error details to clients.
See [references/error-handling-middleware.md](references/error-handling-middleware.md) for the full pattern with `AppError`, `errors.As`, and JSON responses.
Catch panics to prevent a single bad request from crashing the server:
func Recovery(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer func() {
if rec := recover(); rec != nil {
slog.Error("panic recovered",
"panic", rec,
"stack", string(debug.Stack()),
"request_id", RequestIDFromContext(r.Context()),
)
writeJSON(w, 500, map[string]string{"error": "internal server error"})
}
}()
next.ServeHTTP(w, r)
})
}Recovery must be the **outermost** middleware so it catches panics from all inner middleware and handlers. See [references/error-handling-middleware.md](references/error-handling-middleware.md) for details.
Apply middleware outermost-first. The first middleware in the chain wraps all others.
// Nested style (outermost first)
handler := Recovery(
RequestID(
Logger(
Auth(
router,
),
),
),
)
// Or with a chain helper
func Chain(h http.Handler, middleware ...func(http.Handler) http.Handler) http.Handler {
for i := len(middleware) - 1; i >= 0; i-- {
h = middleware[i](h)
}
return h
}
handler := Chain(router, Recovery, RequestID, Logger(slog.Default()), Auth)1. **Recovery** -- outermost; catches panics from all inner middleware 2. **RequestID** -- assign early so all subsequent middleware can reference it 3. **Logger** -- logs the completed request with ID and status 4. **Auth** -- after logging so failed auth attempts are recorded 5. **Application-specific middleware** -- rate limiting, CORS, etc.
Use thes
Image: NASA, Public Domain. Source Beagle is an Agent Skills marketplace: framework-aware code review, documentation, testing, architectural analysis, and git workflows for any compatible coding agent.
Repo: existential-birds/beagle
Guides architectural decisions for Deep Agents applications. Use when deciding between Deep Agents vs alternatives, choosing backend strategies, designing…
Reviews Deep Agents code for bugs, anti-patterns, and improvements. Use when reviewing code that uses create_deep_agent, backends, subagents, middleware, or…
Implements agents using Deep Agents. Use when building agents with create_deep_agent, configuring backends, defining subagents, adding middleware, or setting…
Guides architectural decisions for LangGraph applications. Use when deciding between LangGraph vs alternatives, choosing state management strategies, designing…
Reviews LangGraph code for bugs, anti-patterns, and improvements. Use when reviewing code that uses StateGraph, nodes, edges, checkpointing, or other LangGraph…
Implements stateful agent graphs using LangGraph. Use when building graphs, adding nodes/edges, defining state schemas, implementing checkpointing, handling…