agentleFS
bbvch-aibbvch-ai/aihub-core/.claude/skills/sync-agent-docs/SKILL.md

sync-agent-docs

Skill16 starsChanged 3 days agoApache-2.0View on GitHub

Bring an agent's user-facing documentation page under docs/docs/2_platform/5_agents/ back in line with its implementation. Nothing textually links a doc page to the code behind it, so this drift is invisible to grep and to the generic doc sweeps. Run it whenever a change lands in packages/agent/swiss_ai_hub/agent/{agents,capabilities,imap,rag,mcp,steps}/, packages/agent/app/*/, or an agent config model under packages/core/swiss_ai_hub/core/ -- especially for a feat( commit, which by definition adds behaviour a user-facing page should describe. Use when user says 'the agent docs are out of date', 'sync agent documentation', 'document the new email agent features', 'did the docs keep up with this agent', or after implementing any agent capability, config field or limit. Do NOT use for writing a brand-new agent page from scratch (use document-feature), the generic README/CLAUDE.md staleness sweep (use update-doc), or ADRs (use document-decision).

We split this skill into the rules it gives an agent

8 rules. About 0 are common, 5 are distinctive, and 3 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈5

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 3

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    No match means no agent page can have gone stale from this diff.

    line 34
  2. Very specific:

    Every feat( line is a candidate gap — a feature shipped after the page was last written.

    line 90
  3. Distinctive:

    Read the page, then verify each of these against the implementation.

    line 95
  4. Distinctive:

    No class names, module paths, event types or step-function names.

    line 115
  5. Very specific:

    Keep the page's own voice and structure — :::tip / :::warning containers, tables, mermaid.

    line 116
  6. Distinctive:

    Never state a capability you have not confirmed in the code.

    line 119
  7. Very specific:

    If the change is framework-level rather than agent-level, the developer-facing pages under docs/docs/3_sdk/2_building_agents/ may also need …

    line 126
  8. Distinctive:

    Every locale of the page updated together

    line 169

≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Sync Agent Docs

Each production agent has a user-facing page under docs/docs/2_platform/5_agents/. This skill finds the page for the agent you changed, works out what the page no longer says, and fixes it.

Why this drift is invisible

The agent pages are written for end users, so they never name the implementation class. 11_email_agent does not contain the string ImapAgent; 10_company_knowledge_agent does not contain ExpertRAGAgent. There is no import, no path reference, no shared identifier.

So every ordinary staleness heuristic misses them. grep -rl "$(basename "$f")" docs/ finds nothing. /update-doc's sweep is driven by exactly that kind of name match. The page can sit untouched for months while its agent gains feature after feature, and no tool reports a thing.

packages/agent/CLAUDE.md stays current because developers editing the code read it. The user-facing page has no such reader until a customer hits it.

Step 0: Which agent changed?

BASE=$(git merge-base HEAD origin/main)
git diff --name-only "$BASE"...HEAD | grep -E \
  "^(packages/agent/(swiss_ai_hub/agent/(agents|capabilities|imap|rag|mcp|steps)/|app/)|packages/core/swiss_ai_hub/core/(imap|jira)/)" \
  || echo "no agent-implementation change -- stop here"

No match means no agent page can have gone stale from this diff. Say so and stop.

Note what the paths imply: an agent's doc-relevant code is not confined to its own directory.

Step 1: Map code to doc page

The chat blueprints (llm_wrapping, few_shot, rag, expert_rag, mcp_react, universal) share behaviour through agent/capabilities/ (memory, attached files, # references, tool loop): a change there can alter several pages at once. The join key is the display name. packages/agent/swiss_ai_hub/agent/i18n/translations/agent/<module>.en.yml has a top-level name: that equals the doc page's title:. Derive it rather than trusting the table below:

for f in packages/agent/swiss_ai_hub/agent/i18n/translations/agent/*.en.yml; do
  printf "%-28s :: %s\n" "$(basename "$f" .en.yml)" "$(grep -m1 -E '^  name:' "$f" | sed 's/^  name: *//')"
done

Current mapping — note that code names and product names have almost nothing in common:

Doc pageAgent module (agents/…)Also reads from
3_instructed_assistantllm_wrapping_agentagent/capabilities/
4_teachable_assistantfew_shot_agentagent/steps/, agent/capabilities/
5_document_intelligence_assistantrag_agentagent/rag/, agent/capabilities/
6_retrieval_agentretrieval_agentagent/rag/
7_document_navigation_assistantnamespace_selection_agent
8_mcp_tool_agentmcp_react_agentagent/mcp/, agent/capabilities/
9_expert_coordinator_agentexpert_asking_agent
10_company_knowledge_agentexpert_rag_agentagent/rag/, agent/capabilities/
11_email_agentimap_agentagent/imap/, core/imap/
12_email_classification_agentemail_classification_agentagent/imap/, core/imap/
13_universal_agentuniversal_agentagent/capabilities/ (tool loop)
15_release_notes_assistantrelease_notes_agentcore/jira/
16_anonymiseranonymiser_agentcore/generative_ai/anonymisation/

Two exceptions the derivation cannot give you. imap_agent and memory_writer_agent have no i18n file, so they are absent from the loop's output. imap_agent is 11_email_agent. memory_writer_agent is a non-discoverable system agent with no user-facing page and needs none.

1_fundamentals and 2_blueprints_and_profiles are concept pages, not per-agent pages. They go stale when the framework changes (agent/workflow/, agent/dispatchers/, agent/runners/), not when one agent does.

Step 2: Measure the drift

DOC=docs/docs/2_platform/5_agents/11_email_agent/          # the page
CODE=(packages/agent/swiss_ai_hub/agent/agents/imap_agent/ \
      packages/agent/swiss_ai_hub/agent/imap/ \
      packages/agent/app/imap_agent/ \
      packages/core/swiss_ai_hub/core/imap/)               # everything it describes

SHA=$(git log -1 --format=%H -- "$DOC")
echo "doc last touched: $(git log -1 --format='%ad  %s' --date=short -- "$DOC")"
git log --format="%h %ad %s" --date=short "$SHA"..HEAD -- "${CODE[@]}"

Every feat( line is a candidate gap — a feature shipped after the page was last written. fix( lines matter when they change documented behaviour, a default, or a limit.

Step 3: Check the page against the code

Read the page, then verify each of these against the implementation. They are where drift actually lands:

  • Config tables. Agent pages carry a field-by-field table (field, type, default, description). It must match the config model — including nested groups. These models often live in packages/core, not in the agent package: ImapAgentConfig nests ImapClientConfig and DraftEmailSettings from core/imap/. A field added there changes the Admin UI form and the doc table while touching nothing under packages/agent/. Check a field's presence in the rendered form, not just the model — as_form() deliberately withholds fields (see ImapAgentConfig._draft_form), and a field the admin never sees must not appear in the table.
  • Capability sections. One section per user-visible capability. New @step chains, new start events and new triggers usually mean a new section or a changed flow diagram.
  • Mermaid diagrams. A new branch in the workflow is a new branch in the diagram.
  • Limits and defaults. Message sizes, batch sizes, token budgets, timeouts. These are stated as concrete numbers and silently rot when a constant moves.
  • "What it does not do" claims. The highest-risk section in the file. 11_email_agent promises "there is no SMTP anywhere in it". A negative claim that goes stale is worse than a missing feature — verify each one still holds.

Step 4: Write the update

Match the existing page. These are user-facing docs on the VitePress site, not developer notes:

  • No class names, module paths, event types or step-function names. The reader is an admin configuring the agent.
  • Keep the page's own voice and structure — :::tip / :::warning containers, tables, mermaid. Do not impose a template; see /document-feature for the house style.
  • Describe what the agent now does for the user, not how it was implemented.
  • Never state a capability you have not confirmed in the code. A commit subject is a hint, not a specification — read the diff.

Update every locale the page already has. These pages are index.en.md + index.de.md, written in lockstep and committed together. Shipping only the English leaves the German silently wrong, which is worse than leaving it visibly old. If you cannot write the German, say so explicitly rather than quietly skipping it.

If the change is framework-level rather than agent-level, the developer-facing pages under docs/docs/3_sdk/2_building_agents/ may also need it — and packages/agent/CLAUDE.md is a separate concern from the docs site.

Sweep mode

To find every stale page rather than the one you just changed, iterate the Step 1 table through Step 2.

Snapshot taken 2026-09-18 (doc date, feat( commits since, total commits since):

Doc pageLast doc updatefeats behindcommits behind
10_company_knowledge_agent2026-06-081017
4_teachable_assistant2026-06-01815
3_instructed_assistant2026-06-01813
8_mcp_tool_agent2026-06-0279
7_document_navigation_assistant2026-06-0157
11_email_agent2026-08-1368
9_expert_coordinator_agent2026-06-0833
6_retrieval_agent2026-06-0233
5_document_intelligence_assistant2026-09-1502
12_email_classification_agent2026-09-0711

Recompute before relying on it — it is a starting backlog, not a live view. Treat each page as its own change; a sweep that rewrites ten pages in one PR is unreviewable.

Worked example: the email agent

11_email_agent was last updated 2026-08-13 (#1727). Since then the IMAP code took 8 commits, 6 of them feat(. The page mentions attachments six times but contains no occurrence of PDF, scan, OCR, .eml, data lake or archiv — so at minimum:

  • #1871 attachment text extraction from PDFs, scans and .eml — undocumented
  • #1730 archiving the original message in the data lake — undocumented
  • #1711 creating a missing IMAP target folder when filing — mentioned once, worth verifying against the code

That is the shape of the problem this skill exists to catch.

Done when

  • The page describes every user-visible capability the agent currently has
  • The config table matches the rendered form, nested groups included
  • Limits, defaults and negative claims verified against the code
  • Every locale of the page updated together
  • Nothing asserted that is not in the implementation

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.