--- name: agent-initialization description: Initialize or extend an Agent from a user requirement - write AGENTS.md, set identity metadata, and create, install or import Skills and hook packages (scripts the harness runs on every prompt, before tool calls, or after a task). --- # Agent Initialization This skill initializes an agent's settings from a user requirement — plain files in the target agent's directory. It is also the reference for giving an agent, yourself included, a new Skill or a new hook: both are directories you write, and the harness picks them up from disk. ## Before you start If the user's message only invokes this skill (e.g. "use agent-initialization skill") without a concrete requirement, ask the user what agent they want and what it should do. But when the requirement is already concrete — even a single sentence like "an expert that answers questions about X" — do **not** ask follow-up questions: derive the role and rules from that sentence, apply the defaults below, and list your assumptions in the final reply. ## Resolve the inherited runtime Treat the current Agent as the **Builder**. Resolve the runtime before creating a new Agent: - `provider` and `model_id` are one complete pair. If the user explicitly supplies both, use that pair. If the user supplies neither, inherit the current Builder Session's `Provider` and `Model ID` from the Environment. Reject a half pair. - `thinking_level` is independent. If the user explicitly supplies it, use that value. Otherwise read `model.thinking_level` from the Builder's own `agent_state/system_config.yaml`; when the field is absent, use the normal Agent-config default `medium`. Write the resolved `thinking_level` into a brand-new target Agent's `model.thinking_level`, preserving all other copied `model` fields. Penguin does not persist `provider` or `model_id` in Agent State, so never add either field to `system_config.yaml`. When the same request continues into Benchmark design, carry the resolved model pair forward explicitly so evaluation uses the Builder runtime instead of a Project default. When configuring an existing Agent, change `model.thinking_level` only when the user explicitly requests that runtime change. ## Locate the target agent All agents of this project live side by side under `agents/` in the App Data Dir: ```bash APP_DATA_DIR="" # the App Data Dir value from your Environment section ls "$APP_DATA_DIR/agents" # existing agents (each is a folder here) TARGET="$APP_DATA_DIR/agents/" # the agent to configure ``` An agent directory contains `agent_state/` (`system_config.yaml`, `AGENTS.md`, `skills/`, `hooks/`, `memory/`, `tools/`) plus `scratchpad/` — and `traces/`, which appears once the agent has run at least once. `hooks/` exists once a hook package is installed; create it when you need it. To extend the agent you are running as, the target is your own directory: `/agents/` with the Agent ID from your Environment section. ## Write AGENTS.md `agent_state/AGENTS.md` is injected into the agent's system prompt — it is where the user requirement becomes behavior. Keep `system_config.yaml`'s `system_prompt` untouched (that is the stable system layer); put everything requirement-specific in AGENTS.md: - Role — what the agent is for, in one or two sentences. - Domain guidance — the concrete rules, steps and constraints derived from the user requirement. Be concise: AGENTS.md is prompt context, not documentation. For a domain expert that answers from a knowledge base, a good AGENTS.md is a few lines: the role sentence, "answer strictly from the provided context blocks", citation rules ("cite blocks inline as [1][2]"), a refusal rule for questions the context cannot answer, and "answer in the language of the question". ## Skills A Skill is a directory `agent_state/skills//` containing a `SKILL.md`. The directory name is the Skill's name (letters, digits, `_`, `-`); nothing else registers it. ```md --- name: description: version: --- ``` The `description` line is what the target agent sees in its system prompt, so it has to say when the Skill applies; the body is read only once the agent decides to use it. Optional `short_description` and `short_description_zh` lines give the UI a short blurb. Files the body refers to go beside it (`reference/.md`, scripts), linked by relative path. There are three ways to get one in place: - **Create.** Write the directory yourself. Keep the body to what a capable agent would not already know: the steps, the commands, the traps. - **Install from the library.** Copy the whole `skills//` directory from an agent that has it — `default_agent` ships the whole library. The user can also install from the Web App's Plugins page. - **Import.** Fetch a Skill from a URL, a repository or a local path (`curl`, `git clone`, `unzip`), then place it under `skills/`. A Skill written for another tool usually needs only the frontmatter above. Read everything you fetched in full before installing, and tell the user what it does: a Skill becomes instructions the agent follows in every future session. Do not register Skills in AGENTS.md; the frontmatter is injected automatically. Common library bundles, so you don't under-equip the target: - **App builder** (builds apps or web frontends): `penguin-sdk`, `web-design`, `unified-llm-api`. - **Knowledge expert** (answers questions over a document set): usually **no** harness agent is needed — build a RAG app with the penguin-sdk skill instead, and configure the app's embedded agent (below). - **Evaluation loop**: `benchmark-design`, `agent-evaluation`, `agent-optimization`. When creating a Test Agent, install only the capabilities it needs to solve ordinary tasks. ## Hook packages A hook is a script the harness itself runs at a fixed point of the agent loop. Use one when something must happen every time, whether or not the model remembers: adding context to every prompt, vetting a tool call, deciding that a finished task should continue. A rule the model can simply follow belongs in AGENTS.md or a Skill instead. A hook package is a directory `agent_state/hooks//` holding a `hooks.json` and the scripts it names: ```json { "name": "append-time", "description": "Adds the current local time to every prompt.", "description_zh": "为每条 Prompt 附上当前本地时间。", "version": "2026.09.29.1", "user_prompt": [{ "command": "time.mjs", "timeout": 10 }] } ``` ```js // time.mjs - answers every prompt with the current local time. const now = new Date(); const pad = (n) => String(n).padStart(2, "0"); const offset = -now.getTimezoneOffset(); const stamp = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())} ` + `${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`; const utc = `UTC${offset < 0 ? "-" : "+"}${pad(Math.floor(Math.abs(offset) / 60))}:${pad(Math.abs(offset) % 60)}`; const zone = Intl.DateTimeFormat().resolvedOptions().timeZone; process.stdout.write(`${JSON.stringify({ context: `Current time: ${stamp} ${zone} (${utc})` })}\n`); ``` The three hook points, one command list each in `hooks.json` (leave out the ones you do not use): | Key | Runs | The script answers | | --- | --- | --- | | `user_prompt` | Every time the user submits a prompt | `{ "context": "" }` — sent to the model right behind the user's message | | `pre_tool_use` | Before each tool call is approved | `{ "decision": "allow" \| "deny", "reason": "" }` | | `stop` | After every task ends | `{ "decision": "continue", "input": "" }` to keep going, or `{ "decision": "stop" }` | Every script is plain Node (`.mjs`, builtin modules only), run as `node