speakeasy-api/agent-skills/customize-sdk-hooks
Claude Code and agent skill by speakeasy-api/agent-skills
- community
- ext:[{"type":"hook","description":"Pre/post lifecycle hooks"}]
Checking that the SKILL.md file is still in the repository.
Use when implementing SDK code hooks for custom logic (not spec configuration or runtime overrides). Covers SDK lifecycle hooks: BeforeRequest, AfterSuccess, AfterError for custom headers, telemetry, HMAC signing, and request/response transformation. Triggers on "SDK hooks", "add hooks", "BeforeRequestHook", "custom logic in SDK", "telemetry hook", "SDK middleware", "intercept requests", "HMAC signing hook", "custom code in hooks directory".
Install
npx vskill@latest install speakeasy-api/agent-skills/customize-sdk-hooksSemi-extensibleMentions customization, but needs skill-specific knowledge. Read the extensible skills standard
SKILL.md
Customize SDK Hooks
When to Use
Use this skill when you need to add custom code logic to the generated SDK:
- Add custom headers (User-Agent, correlation IDs) to every SDK request via code
- Implement telemetry, logging, or observability at the SDK level
- Add custom authentication logic (HMAC signatures, token refresh) that runs in SDK code
- Transform responses or errors before they reach the caller
- Implement custom request/response middleware
- User says: "SDK hooks", "add custom logic", "intercept requests with code", "HMAC signing hook", "telemetry in SDK"
NOT for:
- OpenAPI spec modifications (see
manage-openapi-overlays) - Runtime SDK client config (see
configure-sdk-options)
Inputs
- Hook type: Which lifecycle event to intercept (init, before request, after success, after error)
- SDK language: The target language of the generated SDK (TypeScript, Go, Python, Java, C#, Ruby, PHP, etc.)
- Custom logic: The behavior to inject at the hook point
Outputs
- Hook implementation file(s) in
src/hooks/(or language equivalent) - Updated
src/hooks/registration.tsto register the new hook - The hook is preserved across SDK regenerations
Prerequisites
- A Speakeasy-generated SDK (any supported language)
- Understanding of the SDK's request/response lifecycle
- The
src/hooks/directory exists in the generated SDK (created by default)
Hook Types
| Hook | When Called | Common Use Cases | |
|---|---|---|---|
SDKInitHook | SDK client initialization | Configure defaults, validate config, set base URL | |
BeforeCreateRequestHook | Before the HTTP request object is created | Modify input parameters, inject defaults | |
BeforeRequestHook | Before the HTTP request is sent | Add headers, logging, telemetry, sign requests | |
AfterSuccessHook | After a successful HTTP response | Transform response, emit warnings, log metrics | |
AfterErrorHook | After an HTTP error response | Error transformation, retry logic, error logging |
Hook Interfaces (TypeScript)
Directory Structure
Key rule: registration.ts and any custom hook files you create are preserved during SDK regeneration. The types.ts file is regenerated and should not be modified.
Registration Pattern
All hooks are registered in src/hooks/registration.ts. This file is created once by the generator and never overwritten. You add your hooks here:
Command
To add a hook to a Speakeasy-generated SDK:
- Create your hook implementation file in
src/hooks/ - Implement the appropriate interface from
src/hooks/types.ts - Register it in
src/hooks/registration.ts - Regenerate the SDK -- your hooks are preserved
Examples
Example 1: Custom User-Agent Hook
Add a custom User-Agent header to every outgoing request.
Register it:
Example 2: Custom Security Hook (HMAC Signing)
For APIs requiring HMAC signatures or custom authentication that cannot be expressed in the OpenAPI spec, combine an overlay with a BeforeRequestHook.
Step 1: Use an overlay to mark the security scheme so Speakeasy generates the hook point:
Step 2: Implement the signing hook:
Register it:
Best Practices
- Keep hooks focused: Each hook should address a single concern. Use separate
hooks for user-agent, telemetry, and auth rather than one monolithic hook.
- Clone responses before reading the body: The
Response.bodystream can only
be consumed once. Always clone before reading:
``typescript afterSuccess(hookCtx: AfterSuccessHookContext, response: Response): Response { // CORRECT: clone before reading const cloned = response.clone(); cloned.json().then((data) => console.log("Response:", data)); return response; // return the original, unconsumed } ``
- Fire-and-forget for telemetry: Do not block the request pipeline for
non-critical operations like logging or metrics:
``typescript beforeRequest(hookCtx: BeforeRequestHookContext, request: Request): Request { // Fire-and-forget: do not await void fetch("https://telemetry.example.com/events", { method: "POST", body: JSON.stringify({ operation: hookCtx.operationID }), }); return request; } ``
- Test hooks independently: Write unit tests for hooks in isolation by
constructing mock Request/Response objects and hook contexts.
- Use `hookCtx.operationID`: The hook context provides the current operation
ID, which is useful for per-operation behavior, logging, and metrics.
What NOT to Do
- Do NOT edit `types.ts`: This file is regenerated. Your changes will be lost.
- Do NOT consume the response body without cloning: This causes downstream
failures because the body stream is exhausted.
- Do NOT perform blocking I/O in hooks: Long-running operations (network calls,
file I/O) in hooks will degrade SDK performance. Use fire-and-forget patterns for non-critical work.
- Do NOT throw errors in `AfterSuccessHook` unless you intend to convert a
success into a failure. Throwing in hooks disrupts the normal flow.
- Do NOT store mutable shared state in hooks without synchronization. Hooks may
be called concurrently in multi-threaded environments.
- Do NOT duplicate logic that belongs in an OpenAPI overlay. If you need to
modify the API spec (add security schemes, change parameters), use an overlay instead of a hook.
Troubleshooting
Hook is not being called
- Verify the hook is registered in
src/hooks/registration.ts - Confirm you are registering for the correct hook type (e.g.,
registerBeforeRequestHook
vs registerAfterSuccessHook)
- Check that
initHooksis exported and follows the expected signature
Response body is empty or already consumed
- You are reading
response.bodyor callingresponse.json()without cloning first - Always use
response.clone()before consuming the body, then return the original
Hooks lost after regeneration
- Custom hook files in
src/hooks/are preserved, but only if they are separate files registration.tsis never overwritten after initial generationtypes.tsIS overwritten -- never put custom code there
TypeScript compilation errors after regeneration
types.tsmay have updated interfaces. Check for breaking changes in hook signatures- Update your hook implementations to match the new interface definitions
Hook causes request failures
- Ensure you are returning a valid
RequestorResponseobject - Check that cloned requests preserve the original body and headers
- Verify any injected headers have valid values (no undefined or null)
Other Languages
While the examples above are in TypeScript, Speakeasy SDK hooks are available across all supported languages:
- Go: Hooks implement interfaces in
hooks/hooks.gowith registration in
hooks/registration.go
- Python: Hooks are classes in
src/hooks/implementing protocols from
src/hooks/types.py
- Java: Hooks implement interfaces from
hooks/SDKHooks.java - C#: Hooks implement interfaces from
Hooks/SDKHooks.cs - Ruby: Hooks use Sorbet-typed classes with Faraday middleware patterns
- PHP: Hooks use PSR-7 request/response interfaces with Guzzle middleware
The hook types, lifecycle, and registration pattern are consistent across all languages. Refer to the generated types file in your SDK for language-specific interface definitions.
Security
- Security scanPassed, 95 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/customize-sdk-hooks/SKILL.md
Popularity
- Repository stars
- 14
- Repository forks
- 5
- 7-day trend score
- 14
Stars and forks are for the whole GitHub repository, not this skill alone. Refreshed 3 May 2026, 5 months ago.
Extension points
hookPre/post lifecycle hooks
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/speakeasy-api/agent-skills/customize-sdk-hooks)