Skip to content

Teach agents to write agent-friendly tools: a "Designing tools for agents" section in the skill and docs #69

Description

@V3RON

Why

Increasingly, the one registering Appduct tools in an app is itself an agent (the README already says "asking an agent to add Appduct to your app or write its tools? Install the skill"). The skill and docs/TOOLS.md explain the mechanics thoroughly: schema forms, object-rooted roots, timeoutMs, per-mount registration. They say nothing about what makes a tool good for the agent that will call it, so an agent asked to "expose the checkout flow" will happily produce doCheckout(json: object) with no annotations, no output schema and a one-word description. Everything downstream (tools/list in an MCP client, the signature listing from #67, the policy engine keyed on destructiveHint) then degrades.

Tool quality is what a calling agent actually experiences. This is documentation only, and it multiplies the value of every other agent-facing feature.

Proposal

Add a "Designing tools for agents" section to skills/appduct/SKILL.md (the copy an agent reads), with a matching section in docs/TOOLS.md and a pointer from the React Native, iOS and Android READMEs. Each rule gets a one-line reason and a before/after example:

  • Name by intent, not implementation. seed_cart, go_to_checkout, set_feature_flag; never dispatch_action or run_effect.
  • Always set annotations. readOnlyHint on every observer; destructiveHint on anything that deletes, logs out, resets or pays. The daemon's policy engine and the MCP client's permission UI key on these.
  • Pair every mutation with an observer. An agent cannot verify seed_cart without get_cart. Return the resulting state from the mutation itself where it is cheap ({ cartId, items }), so the common case is one call.
  • Declare an outputSchema. It is what makes the result structuredContent over MCP and lets the signature listing show -> { ... }. Wrap non-object results in an object.
  • Describe preconditions and side effects. "Requires a signed-in user. Navigates to the Cart tab." The first line is what the listing shows; keep it one sentence.
  • Describe every parameter (.describe() in zod, description in raw JSON Schema), with units and allowed values; prefer enums over free strings.
  • Make setup tools idempotent (login(userId) is a no-op when already signed in as that user) and say so with idempotentHint.
  • Prefer a few coarse tools over many fine ones. complete_onboarding() beats dismiss_step_1..7. An agent loses more to a long tool list than to a slightly wider tool.
  • Declare timeoutMs on anything that touches the network; the default is 10 s.
  • Do not register tools that need UI cooperation to finish (a tool that opens a modal and resolves when the user taps). Return once the state change is done, or post an app_event for the rest.
  • Keep both schemas object-rooted (already documented; link to it).
  • Name a screen or feature in the description so --filter (feat(cli): agent-friendly output — signature tools listing with filter/paging, table-driven global flags, --pretty/--verbose, compact JSON #67) finds the tool, and use groups once they exist (Tool groups: optional group on the descriptor, --group on tools.list, and lazy group exposure over MCP #70).
  • For the native SDKs: the same rules, phrased for AppductToolDescriptor / registerTool in Swift and Kotlin.

Also add one line to the skill's setup flow: after registering tools, run appduct tools and read the listing back as the calling agent will see it; fix any ..., missing -> { }, or description that does not say what the tool needs.

Acceptance criteria

  • The skill and docs/TOOLS.md carry the section; each rule has an example; the native READMEs link to it.
  • The playground's tools follow the rules (they are the reference an agent copies). Adjust descriptions and annotations there where they do not.
  • docs/CI.md's markdown link check passes.

Out of scope

  • Any automated checking of these rules, in the CLI or in the SDKs. Descriptions and annotations are judgement calls; the guidance is the deliverable.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentation

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions