Skip to content

docs: narrow the getAgent() result in the agents guide samples - #3571

Merged
kojiwakayama merged 2 commits into
mainfrom
fix/dx-20260811-b2-9
Aug 11, 2026
Merged

kojiwakayama merged 2 commits into
mainfrom
fix/dx-20260811-b2-9

Conversation

@kojiwakayama

@kojiwakayama kojiwakayama commented Aug 11, 2026 •

Copy link
Copy Markdown
Contributor

Found during a DX dogfood walk of https://veryfront.com/docs/code/guides/agents, following the published docs literally as a new developer would.

Symptom

Both getAgent() samples in the agents guide (the "Non-streaming response" one and the "Verify it worked" one) are given verbatim as:

const agent = getAgent("assistant");
const result = await agent.generate({ input: "Hello" });

Paste either into a project created by veryfront init and run the typechecker:

app/api/ask/route.ts(8,24): error TS18048: 'agent' is possibly 'undefined'.

The samples work at runtime, so the failure only shows up once the developer runs the typechecker the scaffolder configured for them. The guide never mentions the narrowing and offers no guard.

Root cause

getAgent() returns Agent | undefined (src/agent/composition/composition.ts:216) because the id may not be registered. The scaffolder writes "strict": true into the project tsconfig (cli/commands/init/config-generator.ts:106, and every cli/templates/files/*/tsconfig.json). Under strictNullChecks, calling a method on the result without narrowing is an error. The samples predate that and were never updated.

Reproduced against this tree, not just the published build:

$ deno check sample.ts
TS18048 [ERROR]: 'agent' is possibly 'undefined'.
const result = await agent.generate({ input: "Hello" });
                     ~~~~~

Fix

Add if (!agent) throw new Error("Agent not found: assistant"); to both samples, plus one sentence saying getAgent() returns Agent | undefined and why the guard is there. No API change.

Regression test

tests/docs/guide-content.test.ts — "narrows the possibly-undefined getAgent() result in agents guide samples".

It lives there because docs/guides/agents.md in this repo is the source of truth for the published page (veryfront-docs docs/code/guides/agents.md is synced from it and hand edits there are overwritten), and tests/docs/guide-content.test.ts is the existing home for guide-content contracts. It is also already wired into deno task docs:validate, so it runs in the ci (lint) lane.

The test parses the ts/tsx fences in the guide, finds every const X = getAgent(...) binding that is later dereferenced, and fails unless an if (!X) guard appears before the first use. That is a structural check on the actual defect, not a magic-string assertion, so a future sample that drops the guard fails too.

Confirmed it fails before the fix for the right reason:

AssertionError: Values are not equal: agents guide samples must guard the getAgent() result before using it
-   [ "agent", "agent" ]
+   []

and passes after. deno task docs:validate's guide validators, check-doc-links.ts, deno fmt --check and deno lint are clean on the touched files.

Noted, not fixed here

The same unguarded pattern exists in docs/guides/memory-and-streaming.md (3 samples) and docs/guides/multi-agent.md (agentAsTool(researcher, ...) passes a possibly-undefined value into an Agent parameter). Those are outside this finding's scope and are left for a separate change; the test added here is deliberately scoped to the agents guide so it does not silently claim coverage it does not have.

Summary by CodeRabbit

  • Documentation

    • Updated agent usage examples to handle missing agents safely.
    • Added a clear “Agent not found” error when an agent is unavailable.
  • Tests

    • Added validation to ensure documentation examples check agent availability before use.

@coderabbitai

coderabbitai Bot commented Aug 11, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@kojiwakayama, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 1 minute

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 4db2534a-0f56-4d3b-9a21-15cbea9d9eb3

📥 Commits

Reviewing files that changed from the base of the PR and between 5b18611 and c037656.

📒 Files selected for processing (1)
  • tests/docs/guide-content.test.ts
📝 Walkthrough

Walkthrough

The agent guide now checks getAgent() results before use in two examples. A documentation contract test detects unguarded agent access in fenced TypeScript samples.

Changes

Agent example safety

Layer / File(s) Summary
Guard agent lookups
docs/guides/agents.md
Both getAgent() examples throw an explicit “Agent not found” error before agent use.
Validate sample narrowing
tests/docs/guide-content.test.ts
The contract test detects agent property or optional access before a preceding null guard.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: kwakayama, ariskemper

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the primary documentation change: narrowing the result of getAgent() in the agents guide samples.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/dx-20260811-b2-9

Comment @coderabbitai help to get the list of available commands.

@kojiwakayama

Copy link
Copy Markdown
Contributor Author

Rebased onto current main (was cut before today's eight merges) and pushed a follow-up commit that stays inside this PR's two files.

docs/guides/agents.md — the guard note landed after a sentence ending in a colon, so the colon dangled in front of a prose paragraph instead of the code fence it announced. Folded it into the lead-in sentence. It also has to be ASCII: scripts/docs/validate-public-docs.ts rejects en/em dashes in public docs, which is what deno task docs:validate caught.

tests/docs/guide-content.test.ts — the new assertion indexed regex capture groups (fence[1], binding[1]) without narrowing, so the file stopped type-checking under this repo's noUncheckedIndexedAccess:

TS18048 'code' is possibly 'undefined'.
TS2345  Argument of type 'string | undefined' is not assignable to parameter of type 'string'.

Nothing caught that: docs:validate runs these tests with --no-check, and the test-typecheck ratchet in scripts/lint/check-test-typecheck-baseline.ts:336 only walks src/ and cli/, never tests/. Both captures are now guarded and deno check tests/docs/guide-content.test.ts is clean.

Re-verified red-before-green after the edits: stripping both guards out of the guide still fails the test with agents guide samples must guard the getAgent() result before using it, and it passes with them. deno task docs:validate is green end to end (68 guides, 48 guide-example suites, 1226 doc links).

Scope is unchanged — still the agents guide plus its regression test.

Still deliberately out of scope, as flagged in the description, all verified against this tree:

  • docs/guides/memory-and-streaming.md:112, :118, :215 — three samples dereference the getAgent() result unguarded (TS18048).
  • docs/guides/multi-agent.md:98 — passes a possibly-undefined value into agentAsTool(agent: Agent, description: string) (src/agent/composition/composition.ts:63), so TS2345 rather than TS18048.
  • docs/guides/multi-agent.md:186 binds getAgent("writer") but never dereferences it, so it is not a defect.

Those want their own change with the test widened to cover the guides it actually asserts on; the test here is scoped to the agents guide precisely so it does not claim coverage it does not have.

A separate note for whoever picks that up: the tests/ tree is outside the test-typecheck ratchet entirely, so type rot in any tests/** file is invisible to CI today. That is a pre-existing gap, not something to fix inside a docs PR.

@kojiwakayama

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 11, 2026 •

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@kojiwakayama

Copy link
Copy Markdown
Contributor Author

CI is green on af6465a.

The first run after the rebase went red on three checks, all from one flake: src/transforms/esm/http-cache.test.ts:803 "returns a signal-less cache follower after its bounded wait" (assertEquals got false, wanted true). That is the known flake from #3553. tests (unit) and coverage gate are dependents of the shards, so the single failure surfaced as three red checks.

Note for anyone matching this against the usual report: the flake landed in coverage shard 2/8 this time, not 8/8. Sharding is by file distribution, so the rebase onto current main moved it. Same test, same assertion, same line.

Re-ran the failed jobs on the identical commit and all three passed — shard 2/8 in 2m15s, then tests (unit) and coverage gate. The test was not touched.

The local .husky/pre-push gate also hit an unrelated flake on its first attempt, src/react/components/chat/chat/components/code-block.test.tsx:137 "reports failed copies without leaking the fallback textarea", which passes standalone and passed on the retry that produced this push (3776 passed, 0 failed). Neither flake is reachable from this PR's two files. No --no-verify was used.

@kojiwakayama
kojiwakayama added this pull request to the merge queue Aug 11, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Aug 11, 2026
getAgent() returns Agent | undefined, but both getAgent() samples in the
agents guide called .generate() on the result directly. Pasted verbatim into
a project scaffolded by veryfront init, they fail typecheck with TS18048
under the "strict": true tsconfig the scaffolder itself writes.

Add the missing narrowing guard to both samples and state why it is there.
Follow-ups on the same two files:

- The note landed after a sentence ending in a colon, so the colon dangled in
  front of a prose paragraph instead of the code fence it announced. Fold it
  into the lead-in sentence. Uses ASCII punctuation, which
  validate-public-docs.ts enforces.
- The new assertion indexed regex capture groups without narrowing, so the file
  stopped type-checking under the repo's noUncheckedIndexedAccess. The docs
  lane runs these tests with --no-check and the test-typecheck ratchet only
  walks src/ and cli/, so nothing caught it. Guard both captures.
@kojiwakayama
kojiwakayama added this pull request to the merge queue Aug 11, 2026
Merged via the queue into main with commit e12e5ee Aug 11, 2026
33 checks passed
@kojiwakayama
kojiwakayama deleted the fix/dx-20260811-b2-9 branch August 11, 2026 15:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant