michat-context-aware-tool-design
npx machina-cli add skill filmicgaze/MiChat-desktop/michat-context-aware-tool-design --openclawMiChat Tool Design (Context-Aware)
MiChat tools are contracts for a non-deterministic caller. Constrain capability and scope, not reasoning.
Core principles
-
Profiles are worlds
Treat tool availability as profile-scoped. Only expose tools from enabled toolsets (plus always-on core/scratchpad). -
Bounded capability
Give every tool a hard blast radius (root folder, allow-list, API scope). Prefer "unavailable unless configured" to "available but be careful." -
Navigate before ingest
Design tools so the agent can target information before pulling large text into context (search -> section -> slice, cursor/pagination, stable IDs). -
Context-safe by default
Default outputs to minimum sufficient structure: IDs, counts, short snippets, and navigation hints. Avoid dumping large artifacts by default. -
Workspace for large artifacts
When full text is needed for editing/review, route it to a workspace surface (scratchpad) and return a stub + metadata to the model. -
Verbosity is explicit
When outputs can be large, add explicit controls:- format: "concise" | "detailed" (or "summary" | "full")
- fields: request subsets when helpful
- max_chars / max_items + cursor/start for continuation
Default to the smallest practically useful payload; require explicit opt-in for full or high-volume outputs.
-
Schema stability (tool arguments)
Never define an argument astype: objectwith empty/noproperties. Provide at least a minimal property set, even if you allow extra keys viaadditionalProperties, or the field may be dropped from model-visible schemas. -
Errors must enable recovery
Make errors actionable: what was invalid/missing, expected format, and whether retrying helps (rate limits, transient errors). Avoid generic failures.
Tool description template (MiChat style)
Tool descriptions are contracts, not mini-skills. Keep them clear and functional; put workflow and judgment in skills.
A good description answers:
- What it does (specific, non-vague)
- When to use it (trigger conditions)
- Inputs (what they control; defaults)
- Outputs (shape; what format/verbosity changes; truncation behavior)
- Errors (names + recovery hints)
- Safety boundary (scope gate; what it cannot do)
Keep descriptions short and information-dense. If guidance applies to multiple tools, put it in a skill. Avoid overlapping tool purposes.
Toolset design (toolsets + primitives + skills)
Keep each toolset coherent with a clear domain and blast radius. Keep tools as primitives with non-overlapping contracts; use skills to teach sequencing and judgment.
Consolidate only when it removes real ambiguity:
- If a human cannot confidently pick between two tools, the agent will not either.
- If a split workflow is repeatedly misused, bundle it into a clearer primitive.
Prefer pipelines of distinct intent (e.g., parse -> search -> commit). Avoid near-duplicate tools that differ only by naming or subtle behavior.
Toolsets must not import other toolsets; resolve dependencies at runtime via get_toolset_module.
Toolset docs
When adding or modifying a toolset, ensure toolsets/<toolset_id>/TOOLSET.md exists and is updated to the canonical format.
Output policy (model vs transcript vs workspace)
When outputs can be large, prefer a three-channel model:
A) Model payload (default)
- concise, structured, navigational
- stable IDs and "where to zoom next"
B) Transcript/details payload (optional)
- human-readable audit
- still bounded
C) Workspace payload (when needed)
- full artifact in scratchpad (or other UI)
- tool returns a stub/receipt to the model
Use this pattern for long docs, large lists, and heavyweight state inspection.
Hard caps (robustness)
If output could be large enough to swamp context or UI, implement hard caps with truncation + continuation. Prefer:
- truncated=true + cursor/start token
- clear guidance on how to continue
Naming and conventions
- Tool names: verb_noun, consistent across toolsets
- Parameters: consistent names (path, query, top_k, max_chars, format)
- Return fields: consistent keys (items, count, next_cursor, truncated, summary)
- Avoid cryptic abbreviations
Testing / verification (smoke test)
For each new or changed tool, do:
- 1-2 happy-path calls
- 1 failure case (missing gate / invalid input)
- 1 large-output case (confirm truncation / format controls)
- check unintended exposure for profiles that do not enable it
Anti-patterns to avoid
- Dumping full objects into model context by default
- Overlapping tools with unclear choice
- Side effects at import time (toolsets should be definition-only on import)
- "Safety" implemented as reasoning constraints instead of capability scoping
- Silent destructive edits (writes without clear intent / preview)
Source
git clone https://github.com/filmicgaze/MiChat-desktop/blob/main/.codex/skills/michat-context-aware-tool-design/SKILL.mdView on GitHub Overview
Design or revise MiChat toolsets to enforce unambiguous contracts, strict scope gates, and minimal, navigable outputs. It guides when to add tools, adjust schemas, debug misuse, and refactor tool boundaries while keeping context efficient.
How This Skill Works
Tools are contracts that bound capabilities and exposure by profile. Each tool has a defined blast radius, input/output schemas, and explicit error handling to enable recovery. For large artifacts, outputs route to a workspace (scratchpad) with a stub and metadata, while the model payload remains concise; verbosity is controlled via format and fields, with a preference for stable, minimal payloads.
When to Use It
- When adding a new toolset or tool, to ensure a clear blast radius and non-overlapping purpose.
- When changing tool schemas or outputs, to maintain schema stability and recoverable errors.
- When debugging tool misuse or context bloat, to identify scope creep and route large data to workspaces.
- When refactoring toolset boundaries, to preserve a coherent, pipeline-friendly flow (parse -> search -> commit).
- When updating toolset documentation to reflect canonical contracts and output policies.
Quick Start
- Step 1: Define the tool's scope and blast radius; specify allowed inputs/outputs and exposure rules.
- Step 2: Implement a minimal, stable schema with explicit properties (no bare object types).
- Step 3: Enable three-channel outputs (model payload, transcript, workspace stub) and wire up explicit recovery hints.
Best Practices
- Define a hard blast radius for every tool (root scope, allow-list, API access) and prefer unavailable-by-default behavior.
- Expose tools only from enabled toolsets (plus always-on core/scratchpad) to maintain profile-based visibility.
- Design inputs/outputs with minimal properties; avoid type: object without defined properties to ensure schema stability.
- Route large artifacts to a workspace surface with a stub and metadata, keeping model payload concise.
- Provide actionable error messages that explain what was invalid, how to recover, and whether retrying helps.
Example Use Cases
- When introducing a new search tool, define precise inputs (query, filters) and outputs (IDs, snippets, next-page token) with a concise payload by default.
- Refactor a tool schema to add format and max_chars controls, ensuring the model can request detailed vs. concise results.
- Encounter context bloat; move full-text review tasks to a scratchpad workspace and return navigation hints and a stub to the model.
- Update error handling to clearly indicate missing parameters and expected formats, enabling quick retries or fallbacks.
- Bundle related tools into a single coherent primitive when split workflows cause misuse, reducing ambiguity in tool selection.