[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M72FRF2S5XB6HB0VVPF07DFJ":3,"skill-same:01M72FRF2S5XB6HB0VVPF07DFJ":44},{"skillNo":4,"name":5,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":18,"linkOnly":19,"markdownContent":20,"markdownBody":20,"frontMatter":21,"refName":22,"commitSha":23,"skillDirectory":24,"forksCount":25,"repositoryHtmlUrl":26,"repositoryHomepageUrl":6,"ownerHtmlUrl":27,"ownerBlogUrl":6,"ownerDescription":28,"updatedAt":29,"install":30,"resources":43},"01M72FRF2S5XB6HB0VVPF07DFJ","build-agent",null,"Johnny1110\u002FEVVA","Johnny1110","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F32870491?v=4","01M72FR9VJ3EPP3VYAW7ZN312M","Johnny Wang","01M72FR9WQ7NDYKHJ5V2PY8B6E",2,"MIT","https:\u002F\u002Fgithub.com\u002FJohnny1110\u002FEVVA\u002Fblob\u002Fmain\u002Finternal\u002Fskills\u002Fbundled\u002Fcontent\u002Fbuild-agent\u002FSKILL.md",[],[],"2026-11-10 18:39:20",false,"# build-agent Scaffold a Go program that embeds an evva agent with the evva-sdk (pkg\u002Fagent)\n\nUse this skill when the user wants to BUILD THEIR OWN agent or app on top of evva — \"embed evva in my Go program\", \"build an agent with the evva-sdk\", \"scaffold an evva host\", \"use pkg\u002Fagent\", \"make a custom agent like nono\", \"how do I host evva\". This is about authoring a NEW downstream Go program that imports evva's public `pkg\u002F*` packages. It is NOT about changing the evva repo itself, and NOT about configuring an already-running evva session (for hooks use the `setup-hooks` skill; for MCP servers use `setup-mcp`).\n\n## The mental model: a \"host\"\n\nA program that embeds evva is a **host**. It owns `main()`, picks a UI (or none), and constructs an agent from evva's public `pkg\u002F*` surface — it never imports `internal\u002F` (Go forbids that across modules anyway). Everything is wired through one of two constructors plus a handful of `Option`s.\n\n**Authoritative API, always:** run `go doc github.com\u002Fjohnny1110\u002Fevva\u002Fpkg\u002Fagent` (and `...\u002Fpkg\u002Fconfig`, `...\u002Fpkg\u002Fllm`, `...\u002Fpkg\u002Ftools`, `...\u002Fpkg\u002Fui`, `...\u002Fpkg\u002Fpermission`) to read the EXACT API of the evva version the host imports. That godoc beats any snippet in this skill — snippets here may lag the version on disk. The full prose reference is `docs\u002Fcontributing\u002Fextending.md` in the evva repo, and two runnable templates are the source of truth — read whichever matches the user's goal before writing code:\n\n- `examples\u002Ffull-host\u002Fmain.go` (~60 lines) — the batteries-included path: interactive TUI, persona catalog + `\u002Fprofile` switching, permission prompts, `\u002Fresume`, `\u002Fcompact`, background tasks. Built on the one-call `agent.New(Config)`. It is a SEPARATE Go module (its own `go.mod` with a `replace`), which proves the public surface is self-sufficient.\n- `examples\u002Fminimal-host\u002Fmain.go` (~150 lines) — the à-la-carte path: `agent.NewWithProfile` plus a custom provider, a custom tool, and a custom skill, with a JSON event sink and no TUI.\n\nIf the evva source isn't on disk (the user is in their own repo), the patterns below are self-contained — scaffold from them directly, and fetch the example files from the evva repository only if you need more detail.\n\n## Step 1 — Clarify the goal (use ask_user_question if unclear)\n\nPin down four things before writing any code:\n\n1. **Interactive or headless?** A TUI app a human drives, or a one-shot \u002F automation that returns text and exits.\n2. **Which LLM provider?** A built-in (`anthropic`, `deepseek`, `openai`, `ollama`) or a custom one.\n3. **Default tools, a kit, or custom?** The standard evva catalog, a named kit from `pkg\u002Ftools\u002Fkits`, or bespoke tools.\n4. **One persona or several?** Just the default `evva`, or a custom persona (the evva→nono pattern), possibly several switchable ones.\n\nThe answers decide the constructor (Step 2) and which extension points you wire (Step 4). Don't wire anything the goal doesn't call for.\n\n## Step 2 — Pick the constructor\n\n| Goal | Constructor | Why |\n| --- | --- | --- |\n| Full app, fastest path | `agent.New(agent.Config{...}, opts...)` | One call wires persona resolution (with an `evva` fallback), memory, the skill catalog, the permission store + mode, and the approval + question brokers — all from `Config`. Mirror `examples\u002Ffull-host`. |\n| Fine-grained \u002F headless \u002F custom wiring | `agent.NewWithProfile(profile, opts...)` | À-la-carte: it wires only what you pass. Mirror `examples\u002Fminimal-host`. |\n\n**Default to `agent.New(Config)`** unless the user needs à-la-carte control — it is dramatically less code (a full TUI app is ~40 lines).\n\n## Step 3 — Scaffold the project\n\n1. If it's a new program: `go mod init \u003Cmodule-path>`. If the user already has a module, add to it — don't scaffold a competing one.\n2. Add the dependency: `go get github.com\u002Fjohnny1110\u002Fevva@latest` (for local development against an evva checkout, use a `replace` directive instead — see `examples\u002Ffull-host\u002Fgo.mod`).\n3. Blank-import the providers so the built-ins register: `_ \"github.com\u002Fjohnny1110\u002Fevva\u002Fpkg\u002Fllm\u002Fbuiltins\"`.\n4. Write `main.go` from the matching template below.\n\n### 3a — Batteries-included host (most users)\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"os\u002Fsignal\"\n\t\"syscall\"\n\n\t\"github.com\u002Fjohnny1110\u002Fevva\u002Fpkg\u002Fagent\"\n\t\"github.com\u002Fjohnny1110\u002Fevva\u002Fpkg\u002Fconfig\"\n\t_ \"github.com\u002Fjohnny1110\u002Fevva\u002Fpkg\u002Fllm\u002Fbuiltins\" \u002F\u002F register anthropic\u002Fdeepseek\u002Fopenai\u002Follama\n\t\"github.com\u002Fjohnny1110\u002Fevva\u002Fpkg\u002Fui\u002Fbubbletea\"\n)\n\nfunc main() {\n\tcfg := config.Get()\n\n\tctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)\n\tdefer stop()\n\n\ttui := bubbletea.New(cfg.AppHome) \u002F\u002F the UI is the agent's event sink\n\n\tag, err := agent.New(agent.Config{AppConfig: cfg},\n\t\tagent.WithSink(tui),\n\t\tagent.WithRootContext(ctx),\n\t)\n\tif err != nil {\n\t\tfmt.Fprintln(os.Stderr, \"host:\", err)\n\t\tos.Exit(1)\n\t}\n\tdefer ag.Shutdown()\n\n\ttui.Attach(ag.Controller()) \u002F\u002F ag.Controller() is the ui.Controller view\n\tif err := tui.Run(ctx); err != nil {\n\t\tfmt.Fprintln(os.Stderr, \"host:\", err)\n\t\tos.Exit(1)\n\t}\n}\n```\n\n### 3b — Headless host (automation, no UI)\n\nA non-interactive host has no UI to resolve approval prompts, so it MUST opt out of the gate — otherwise every tool call that needs approval auto-denies and silently fails.\n\n```go\nag, err := agent.NewWithProfile(profile,\n\tagent.WithConfig(cfg),\n\tagent.WithSink(jsonSink{enc: json.NewEncoder(os.Stdout)}), \u002F\u002F your event.Sink\n\tagent.WithHeadlessBypass(), \u002F\u002F REQUIRED for non-interactive hosts: auto-allow all tools\n)\n\u002F\u002F ... then ag.Controller().Run(ctx, prompt) and consume events from your sink.\n```\n\n`WithHeadlessBypass()` auto-allows every tool — use ONLY in trusted environments (CI runners, sandboxes, ephemeral VMs). If the host has any approval UI, omit it and wire real approvals via `Agent.RespondPermission`.\n\n## Step 4 — Wire only the extension points the goal calls for\n\nEach bullet is one section of `docs\u002Fcontributing\u002Fextending.md` — read that section (or `go doc` the package) for the exact contract.\n\n- **Custom LLM provider** — implement `pkg\u002Fllm.Client` (`Name`, `Model`, `Complete`, `Stream`, `Apply`), register a factory on `llm.DefaultRegistry().MustRegister(name, factory)`, then install creds: `cfg.LLMProviderConfig[name] = config.APIConfig{ApiURL: ..., ApiSecret: os.Getenv(...)}`.\n- **Custom tool** — implement `pkg\u002Ftools.Tool` (`Name`, `Description`, `Schema`, `Execute`). For one agent: `agent.WithCustomTool(name, func(s tools.State) (tools.Tool, error) { ... })`. Process-wide: `toolset.DefaultRegistry().MustRegister(name, factory)` in an `init()`.\n- **Tool kits** — instead of hand-assembling tool-name lists, use `kits.GeneralPurposeKit()` \u002F `ReadOnlyKit()` \u002F `CodingKit()` \u002F `ResearchKit()` from `pkg\u002Ftools\u002Fkits`; each returns `(active, deferred)` name slices you can `append` to.\n- **Custom persona (evva→nono)** — `reg, _ := agent.BuildAgentRegistry(cfg.AppHome)`, then `reg.Register(agent.AgentDefinition{Name: \"nono\", WhenToUse: \"...\", As: []string{\"main\", \"subagent\"}, InjectMemory: true, SystemPrompt: \"...\"})`. Pass `Personas: reg, Persona: \"nono\"` in `agent.Config`. Or drop `\u003CAppHome>\u002Fagents\u002F\u003Cname>\u002F{system_prompt.md,tools.yml,meta.yml}` on disk — `New(Config)` loads them automatically.\n- **Custom event sink** — implement `pkg\u002Fevent.Sink` (one method, `Emit(event.Event)`); pass `agent.WithSink(s)`. Fan out with `event.Multi{Sinks: [...]}`. Type-switch on a payload with `e.Payload()`.\n- **Custom UI** — implement `pkg\u002Fui.UI` (`Emit`, `Attach`, `Run`) and drive the `Controller`; or just embed `pkg\u002Fui\u002Fbubbletea`.\n- **Permissions** — `permission.Load(cfg.WorkDir, cfg.AppHome)` for disk rules (`New(Config)` does this for you). For a programmatic allow\u002Fdeny policy: build `permission.NewBroker()`, register `permission.SetOnRequest(func(req) Decision { ... })`, pass `agent.WithPermissionBroker(b)`.\n- **Custom skills** — `reg := skill.NewRegistry(); reg.Add(skill.SkillMeta{Name, Description, BodyFunc})`; pass `agent.WithSkillRegistry(reg)`. NOTE: an explicit registry SKIPS the disk + bundled auto-load, so include any built-ins you still want.\n- **Custom AppHome \u002F config** — `config.Load(config.LoadOptions{AppName, AppHome, WorkDir, ProviderCredentials, EnvAliases, SeedEnvTemplate})` for a fully branded app with its own home dir and declarative env wiring.\n- **Hooks \u002F MCP** — config-driven via `settings.json`; `agent.New(Config)` auto-loads both. To CONFIGURE them in a running session, the user wants the `setup-hooks` \u002F `setup-mcp` skills, not this one.\n\n## Step 5 — What you CANNOT change (say so up front)\n\nThese are fixed by design (see `extending.md` \"What you can't change\"):\n\n- The set of `pkg\u002Fevent.Kind` constants — fixed at the evva version you import; a new kind needs a change in evva itself.\n- The agent loop shape — `iter → LLM call → dispatch tools → fold results → repeat` is internal and not configurable.\n- The bundled sysprompt builders — a custom persona injects its OWN full system prompt (via the `AgentDefinition` \u002F `NewProfile`), it doesn't edit evva's.\n\nIf the user needs one of these, the answer is \"fork or file an issue\", not \"import internal\u002F\".\n\n## Step 6 — Verify it compiles and runs\n\nNever hand the user code you haven't checked:\n\n1. `go build .\u002F...` — fix every error before continuing.\n2. If the host is its own module AND embeds the bundled TUI (`pkg\u002Fui\u002Fbubbletea`), pin the charmbracelet versions to evva's (a different bubbletea major\u002Fminor makes the two `tea.Program` types fail to unify at the `UI.Run` boundary — see `extending.md` \"Charmbracelet version pinning\"), or run `go mod tidy` to resolve to evva's transitive pins.\n3. Confirm a provider credential is set (the relevant `*_API_KEY` env var or `.env`) before the first run, or the first LLM call fails.\n4. Run it: `go run .` (TUI) or pipe a prompt to the headless binary. Confirm one full ReAct turn end to end.\n\n## Guardrails\n\n- NEVER import `internal\u002F` — it won't compile across modules and isn't the supported surface. If a capability looks internal-only, it's almost certainly a public symbol you haven't found yet: check the `extending.md` package table or `go doc`, don't reach in.\n- Keep the host SMALL. The point of `agent.New(Config)` is that ~40 lines buys a full app — don't re-hand-wire what the constructor already does.\n- Match the user's existing module and Go toolchain; add to their `go.mod` rather than creating a parallel module.\n- This skill scaffolds a NEW host program. It does not modify the evva repository, and it is not how you configure a running evva session.\n",{},"main","7ae8d7a9c769f9b4db97cbdad71bd8117bfab983","internal\u002Fskills\u002Fbundled\u002Fcontent\u002Fbuild-agent",3,"https:\u002F\u002Fgithub.com\u002FJohnny1110\u002FEVVA","https:\u002F\u002Fgithub.com\u002FJohnny1110","Stay Hungry & Humble.","2026-08-04 11:46:50",{"source":7,"skillName":5,"commands":31,"prompt":41,"zipAvailable":42},[32,35,38],{"tool":33,"command":34},"npx","npx skills add Johnny1110\u002FEVVA --skill build-agent",{"tool":36,"command":37},"bunx","bunx skills add Johnny1110\u002FEVVA --skill build-agent",{"tool":39,"command":40},"pnpm","pnpm dlx skills add Johnny1110\u002FEVVA --skill build-agent","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FJohnny1110\u002FEVVA\u002Fblob\u002Fmain\u002Finternal\u002Fskills\u002Fbundled\u002Fcontent\u002Fbuild-agent\u002FSKILL.md",true,[],[45,51,57,63,69,75],{"skillNo":46,"name":47,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":48,"categories":49,"keywords":50,"publishedAt":18},"01M72FS2CSWGA31Q3SC4T5BFK2","standup","https:\u002F\u002Fgithub.com\u002FJohnny1110\u002FEVVA\u002Fblob\u002Fmain\u002Finternal\u002Fswarm\u002Fagentdef\u002Ftestdata\u002Fagents\u002Fmain\u002Fleader\u002Fskills\u002Fstandup\u002FSKILL.md",[],[],{"skillNo":52,"name":53,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":54,"categories":55,"keywords":56,"publishedAt":18},"01M72FRZNEXBHR1BNTKTNW6YZQ","simplify","https:\u002F\u002Fgithub.com\u002FJohnny1110\u002FEVVA\u002Fblob\u002Fmain\u002Finternal\u002Fskills\u002Fbundled\u002Fcontent\u002Fsimplify\u002FSKILL.md",[],[],{"skillNo":58,"name":59,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":60,"categories":61,"keywords":62,"publishedAt":18},"01M72FRX9VW4GFP0H4CFQ01NAH","setup-swarm","https:\u002F\u002Fgithub.com\u002FJohnny1110\u002FEVVA\u002Fblob\u002Fmain\u002Finternal\u002Fskills\u002Fbundled\u002Fcontent\u002Fsetup-swarm\u002FSKILL.md",[],[],{"skillNo":64,"name":65,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":66,"categories":67,"keywords":68,"publishedAt":18},"01M72FRSX9TDN3SJJ679PAEWE7","setup-mcp","https:\u002F\u002Fgithub.com\u002FJohnny1110\u002FEVVA\u002Fblob\u002Fmain\u002Finternal\u002Fskills\u002Fbundled\u002Fcontent\u002Fsetup-mcp\u002FSKILL.md",[],[],{"skillNo":70,"name":71,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":72,"categories":73,"keywords":74,"publishedAt":18},"01M72FRQC6J70KXF6JVBY22YX7","setup-hooks","https:\u002F\u002Fgithub.com\u002FJohnny1110\u002FEVVA\u002Fblob\u002Fmain\u002Finternal\u002Fskills\u002Fbundled\u002Fcontent\u002Fsetup-hooks\u002FSKILL.md",[],[],{"skillNo":76,"name":77,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":78,"categories":79,"keywords":80,"publishedAt":18},"01M72FRNC0NWJABHM2V20ZTSRZ","security-review","https:\u002F\u002Fgithub.com\u002FJohnny1110\u002FEVVA\u002Fblob\u002Fmain\u002Finternal\u002Fskills\u002Fbundled\u002Fcontent\u002Fsecurity-review\u002FSKILL.md",[],[]]