Walk a Go developer through embedding core-agent in their own binary. Use when the user asks "how do I embed core-agent", "use core-agent as a library", "build my own agent on core-agent", "agent.New", "custom prompter", "custom tools", "custom provider", "HTTP-served agent", "integrate core-agent into [Go project]", or asks any question implying they want to use the Go API rather than the bundled CLI.
Installs into .claude/skills of the current project.
Are you the author of Library Embedding?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/go-steer-library-embedding)
---
name: library-embedding
description: Walk a Go developer through embedding core-agent in their own binary. Use when the user asks "how do I embed core-agent", "use core-agent as a library", "build my own agent on core-agent", "agent.New", "custom prompter", "custom tools", "custom provider", "HTTP-served agent", "integrate core-agent into [Go project]", or asks any question implying they want to use the Go API rather than the bundled CLI.
---
When invoked:
1. **Confirm the use case.** Embedding fits when:
- You're building a domain-specific agent (web service, custom UI, IDE plugin)
- You need extension points the CLI doesn't expose (custom prompter, custom tools, custom provider)
- You're wrapping `core-agent` in a larger system (orchestrator, agent platform)
If the user just wants to customize `core-agent`'s behavior for their project, the CLI + skills covers it without embedding. Walk them to the `cli-setup` skill instead.
2. **Start with the minimal embed.** Show the 20-line "hello world" — `agent.New` + `Run` + iterate events. Most embedding work builds on this base. Use `references/minimal-embed.md`.
3. **Identify the extension point they need.** Most embedding use cases come down to one of:
- Custom **Prompter** — different approval UX (web modal, Slack button, IDE dialog)
- Custom **tool** — domain operations the built-in nine don't cover
- Custom **Provider** — LLM backend not in the box (local Ollama, internal model server)
- Custom **session.Service** — persistence beyond eventlog (Redis, custom DB)
- **`RemoteAgentSpawner`** — delegate background subagents to K8s Jobs, Cloud Run, etc.
Fetch `references/extension-points.md` to walk them through the relevant one.
4. **Show a full worked example.** For non-trivial embeddings (web service, HTTP-served agent), build out a complete program. Use `references/http-served-agent.md` for the canonical example.
5. **Discuss long-term maintenance.** `core-agent` is pre-1.0; breaking changes can land at any minor version. If the user is shipping production code on top of it:
- Pin the dep version in `go.mod`
- Subscribe to releases / `CHANGELOG.md`
- Use the documented `agent.Option` interface — not internal/private symbols
## Triggers in detail
Beyond the description, also match on:
- "How do I add a custom tool to core-agent"
- "Build an HTTP-served agent"
- "Background workers with core-agent"
- "Integrate core-agent into my existing Go service"
- "Customize the approval UX for a web app"
- "Bring my own LLM backend"
- "Programmatic control of an agent run"
## References
Fetch based on what the user is building:
- **`references/minimal-embed.md`** — the smallest working `agent.New` + `Run` loop. Read first for any embedding question; it's the foundation.
- **`references/extension-points.md`** — the seven main customization surfaces (`WithTools`, `WithPrompter`, `WithProvider`, `WithSessionService`, `WithCompactor`, `WithCheckpointer`, `RemoteAgentSpawner`) with one paragraph per. Read when narrowing in on the user's specific extension need.
- **`references/http-served-agent.md`** — full worked HTTP-served agent example. Read when the user is building a web-facing service; covers session-per-request vs persistent-session shapes, prompter integration, streaming responses.
## Procedure: minimal embed
Walk the user through this skeleton first. Everything else is variations on it:
```go
package main
import (
"context"
"fmt"
"log"
"os"
"github.com/go-steer/core-agent/v2/pkg/agent"
"github.com/go-steer/core-agent/v2/pkg/models"
_ "github.com/go-steer/core-agent/v2/pkg/models/gemini"
)
func main() {
ctx := context.Background()
provider, err := models.Resolve(nil) // reads .agents/config.json
if err != nil { log.Fatal(err) }
model, err := provider.Model(ctx, "gemini-3.7-flash")
if err != nil { log.Fatal(err) }
a, err := agent.New(model)
if err != nil { log.Fatal(err) }
prompt := os.Args[1]
for ev, err := range a.Run(ctx, prompt) {
if err != nil { log.Fatal(err) }
if ev.Content != nil {
for _, p := range ev.Content.Parts {
if p.Text != "" {
fmt.Print(p.Text)
}
}
}
}
fmt.Println()
}
```
That's it. Multi-turn conversation: call `a.Run(ctx, prompt)` again with a new prompt — session history is preserved automatically. Run-to-completion (no streaming): use `runner.Headless` instead.
## Procedure: pick extension points
Walk the user through what they're customizing:
| Want | Extension | Reference |
|---|---|---|
| Different approval UX | `WithPrompter(impl)` | `references/extension-points.md` § Prompter |
| Domain-specific tool | `WithTools([]tool.Tool{...})` | `references/extension-points.md` § Tools |
| LLM backend not in box | Implement `models.Provider`, register with `models.Register` | `references/extension-points.md` § Provider |
| Custom persistence | `WithSessionService(impl)` | `references/extension-points.md` § Session |
| Long-session survival | `WithCompactor(...)` + `WithCheckpointer(...)` | (built-in defaults usually fine) |
| Distributed subagent execution | Implement `background.RemoteAgentSpawner` | `references/extension-points.md` § Remote subagents |
| HTTP-served agent | All of the above + handler shape | `references/http-served-agent.md` |
For each one, fetch the relevant section and walk through the implementation contract + a minimal example.
## Procedure: structured persistence
If the user is building anything beyond a one-shot CLI, push them toward durable sessions early:
```go
import "github.com/go-steer/core-agent/v2/pkg/eventlog"
import "github.com/glebarez/sqlite"
handle, err := eventlog.Open(ctx, sqlite.Open("./sessions.db"))
if err != nil { log.Fatal(err) }
defer handle.Close()
a, err := agent.New(model,
agent.WithSessionService(handle.Service),
agent.WithEventLog(handle),
)
```
Now every turn, every tool call, every model response lands in `sessions.db`. Crash-resume, audit log, replay, live tail — all unlocked.
## Procedure: composition with autonomous + subagents
If the embedded agent is itself autonomous OR spawns subagents, use `RunAutonomous` + `background.Manager`:
```go
import "github.com/go-steer/core-agent/v2/pkg/agent"
bgMgr, err := agent.NewBackgroundAgentManager(
agent.WithBackgroundProvider(provider, "gemini-2.5-flash"),
agent.WithBackgroundGate(gate),
agent.WithBackgroundCatalog(builtinTools),
)
if err != nil { log.Fatal(err) }
defer bgMgr.Close()
a, err := agent.New(model,
agent.WithBackgroundManager(bgMgr),
agent.WithTools(append(builtinTools, agent.NewBackgroundSpawnTools(bgMgr)...)),
)
```
The parent now has `spawn_agent` and `stop_agent` (subagent results are pushed back via the `[Background reports]` block; `spawn_agent { wait: true }` blocks inline). The user's `AGENTS.md` (or in-prompt instruction) governs when to use them.
## When NOT to use this skill
- The user is using the **bundled CLI** (`core-agent` binary) and asking about configuration. Use `cli-setup` skill.
- The user is configuring **autonomous / unattended runs** of the bundled CLI. Use `autonomous-setup` skill.
- The user is asking a reference question (function signature, type definition). Answer directly from [library/api]({{< relref "library/api.md" >}}) docs; no need to walk the whole embedding procedure.
- The user wants to **modify `core-agent` itself** (contribute upstream changes). That's a different conversation; point them at `CONTRIBUTING.md`.
## Output style
Code-heavy but with clear narrative. Embedding work is mostly Go — show the code, explain what each block does. Don't generate a wall of code without explanation; the user is going to maintain it.
For non-trivial embeddings, propose a project layout (`cmd/`, `internal/`, etc.) before writing code. Give the user a sense of where things go so the snippets fit into context.
When showing extension points, ALWAYS include the interface contract being satisfied. E.g., "you need to implement `permissions.Prompter` which is `interface { AskApproval(ctx, req) (Decision, error) }`" — not just "implement a prompter."