> For the complete documentation index, see [llms.txt](/llms.txt).
> A full single-fetch corpus is available at [llms-full.txt](/llms-full.txt).
---
last_verified: 2026-10-09
title: Functions
description: Register typed Go functions with RegisterFunction, configure retries and schemas, and call them from workflows
category: Go SDK
hideRightSidebar: true
---

A function is one unit of work with retries and tracing. In Go it is a typed handler that you register with the worker. For a guided introduction, see [Functions](/docs/build/functions.md).

## `agnt5.RegisterFunction`

```go
func RegisterFunction[In any, Out any](
	w *Worker,
	name string,
	handler func(*Context, In) (Out, error),
	opts ...ComponentOption,
) error
```

```go
type EmailInput struct {
	To      string `json:"to"`
	Subject string `json:"subject"`
}

func sendEmail(ctx *agnt5.Context, in EmailInput) (string, error) {
	ctx.Logger().Info("Sending email", "to", in.To)
	return "Sent to " + in.To, nil
}

err := agnt5.RegisterFunction(worker, "send_email", sendEmail)
```

`name` is the name you pass to `agnt5 run` or the API. The run's JSON input is decoded into `In`, and the returned `Out` is encoded as the run's output, so use struct tags to match the JSON field names. Return a non-nil `error` to fail the try.

## Options

Pass `ComponentOption`s after the handler:

| Option | Description |
|---|---|
| `agnt5.WithRetry(maxAttempts, initialIntervalMS, maxIntervalMS)` | Total tries including the first, the wait before the first retry, and the longest wait. |
| `agnt5.WithBackoff(backoffType, multiplier)` | `"constant"`, `"linear"`, or `"exponential"`, and how fast the wait grows. |
| `agnt5.WithInputSchema(schema)`, `agnt5.WithOutputSchema(schema)` | JSON Schema for the input and output, as `map[string]any`. |

```go
err := agnt5.RegisterFunction(worker, "send_email", sendEmail,
	agnt5.WithRetry(5, 500, 30000),
	agnt5.WithBackoff("exponential", 2.0),
	agnt5.WithInputSchema(map[string]any{
		"type":       "object",
		"properties": map[string]any{"to": map[string]any{"type": "string"}},
		"required":   []any{"to"},
	}),
)
```

When every try fails, the run fails with the last error. `ctx.Attempt()` is `0` on the first try, `1` on the first retry, and so on.

## Call a function

| From | Call | Checkpointed |
|---|---|---|
| A workflow | `agnt5.Task(ctx, "send_email", in, sendEmail)` | Yes. On replay the saved result is returned. |
| A workflow, as a closure | `agnt5.Step(ctx, "send_email", func(context.Context) (string, error) { return sendEmail(ctx, in) })` | Yes. |
| Go code | `sendEmail(ctx, in)` | Runs as part of the caller. |
| The CLI | `agnt5 run send_email --input '{"to": "a@example.com"}'` | Its own run. |

See [Workflows](/sdk/go/workflows.md) for `Task` and `Step`.

## Next steps

* [Workflows](/sdk/go/workflows.md): run functions as checkpointed steps.
* [Context API](/sdk/go/context.md): everything a handler can do with `ctx`.
* [Functions guide](/docs/build/functions.md): retries and timeouts in practice.
