remedy is a small Go library for structured business errors that help agents recover fast.
Most error packages stop at message + cause. That is enough for logs, but weak for agentic systems. An agent usually needs one more thing: a short, inline instruction telling it what to try next.
remedy packages that feedback into the error itself:
- HTTP status for transports
- Stable machine-readable codes for branching
- Human-readable messages
- Inline recovery guidance for agents, CLIs, and API clients
- Standard
errorwrapping support
The practical benefit is token efficiency. Instead of failing with a vague message, then spending extra turns and tokens to explain recovery, your tool or API can return the fix with the failure.
remedy is also packaged with a companion agent skill. Install the skill alongside the library so agents have both the runtime API and the usage patterns for when to add recovery hints, how to format them at tool boundaries, and how to test them.
go get github.com/CaliLuke/remedy@latestInstall the companion agent skill from this repository as well if your agents will be authoring or reviewing remedy usage.
Use remedy when the caller can take corrective action.
Good fit:
- MCP tools and agent-facing APIs
- validation-heavy services
- HTTP or RPC layers that need status + error code mapping
- CLI flows where the next step should be obvious
Less useful:
- deep infrastructure errors with no user action
- internal-only code paths where plain
%wis enough
This is the core pattern extracted from Auto-K:
package main
import (
"fmt"
"github.com/CaliLuke/remedy"
)
func main() {
err := remedy.NotFound("project %q was not found", "abc123").
WithRecovery("Verify the project ID and retry")
fmt.Println(remedy.GetStatus(err))
fmt.Println(remedy.GetCode(err))
fmt.Println(remedy.FormatForAgent(err))
}Output:
404
not_found
[not_found] project "abc123" was not found
-> Recovery: Verify the project ID and retry
When you already have the pieces, use the shared formatter directly:
msg := remedy.FormatForAgentParts("not_found", "project was not found", "Verify the project ID and retry")Format the error once, at the edge:
func codedErrorToTool(err error) string {
return remedy.FormatForAgent(err)
}That keeps the recovery hint inline with the failure, which is exactly what agent callers need to self-correct without wasting precious tokens on follow-up retries or extra explanation.
Map remedy.Error at the HTTP or RPC boundary instead of scattering transport logic through service code.
func statusFromErr(err error) int {
return remedy.GetStatus(err)
}Constructor helpers:
remedy.BadRequestremedy.Unauthorizedremedy.Forbiddenremedy.NotFoundremedy.Conflictremedy.Internalremedy.New
Fluent modifiers:
(*remedy.Error).WithCode(*remedy.Error).WithRecovery(*remedy.Error).Wrap
Consumers:
remedy.Asremedy.GetStatusremedy.GetCoderemedy.GetRecoveryremedy.FormatForAgentremedy.FormatForAgentParts
Create remedy errors close to the business rule that failed. Add WithRecovery(...) only when the caller can actually do something with it. Keep recovery text short, concrete, and immediately actionable.