Add TypeScript tabs to the graph workflow pages - #2167
Conversation
The five /graphs/ pages documented graph workflows for Python and Go only, so a TypeScript reader had to infer the API from the Python tab — which does not translate: TypeScript has no `@node` decorator, schemas are Zod objects rather than pydantic models, state is written through `ctx.state` instead of returned on an event, and a user-facing message is the event's `content` rather than a `message` field. Every section that has a Python tab now has a TypeScript tab before the Go one, backed by 26 snippet files under examples/typescript/snippets/graphs/. The snippets are ported from the runnable samples in adk-js (samples/workflows/), which already map 1:1 to these section anchors, and they all type-check against the adk-js workflow API. The tabs also call out the behaviours that are easy to get wrong and have no Python equivalent: `ctx.runNode()` resolves to a node result rather than the output, and does not throw when a child interrupts; a second event carrying `output` silently overwrites the first; `LlmAgent.inputSchema` is not the node's input contract inside a graph.
✅ Deploy Preview for adk-docs-preview ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
The `//` annotations inside the snippet regions duplicated the prose that already introduces each tab, and they were the first thing a reader saw in a rendered sample rather than the API itself. Removes the 83 `//` comments inside the `--8<--` regions across all 26 files. JSDoc blocks stay, since they document what a function or schema is rather than annotating a line; the Apache headers and the per-file orientation comments above each region are untouched, and neither renders on the docs site anyway. Verified comment-only: compiling every file before and after with `tsc --removeComments` produces byte-identical `.js` and `.d.ts` output across all 52 emitted files.
The 26 files landed double-quoted, which reads as a deliberate choice next to the existing TypeScript snippets under examples/typescript/snippets/ — those are predominantly single-quoted (49 of 68 imports). The repo has no prettier config, so nothing enforces either style; this just stops the new directory looking different from its neighbours. Formatting only: `prettier --no-config --single-quote`, and every changed line differs from the original by a quote character alone. Compiling before and after with `tsc --removeComments` produces output whose only differences are the same quote swaps, since tsc preserves the source quote style.
Porting samples/workflows/routes/nested_workflow inlined the `titleCase` helper and dropped the check that a character's uppercase form is a single code point, along with the comment explaining why it is there. That changed behaviour for word-initial characters whose uppercase expands: "first draft" became "FIrst Draft" and "ßeta test" became "SSeta Test", where upstream leaves both alone. Restores the helper, the guard and the rationale. Because the helper sits inside the --8<-- region, the explanation now renders on the page as well, so the next person to touch it can see what the guard is for. Also restores an unused `_ctx` parameter in the user_message snippet, the only other place the port had drifted from upstream. Verified by compiling each of the 26 snippets and its upstream counterpart at adk-v2.0.0 with `tsc --removeComments` and comparing the emitted JavaScript: all 26 are now semantically identical to samples/workflows/.
joefernandez
left a comment
There was a problem hiding this comment.
Thanks for the update. Please address comments.
…tabs Wording, across all TypeScript tabs: - No sentence starts with code syntax. "`route` is independent of..." becomes "The `route` value is independent of...", and the same for the other cases. - Removed informal and editorial phrasing: "earn their keep", "dropped straight into", "reach for", "hands you", "two things to know going in", "kick the children off", "fails loudly". - Spelled out "/" as "and" in the `inputSchema` and `outputSchema` sentence. - Described the `ctx.runNode()` interrupt behaviour in full rather than only as "does not throw": it returns normally with `interruptIds` populated and `output` undefined, and an orchestrator that skips the check continues with a value the user never supplied. - Explained what a JoinNode waits for instead of referring to "the barrier". - Tied the `rerunOnResume` option back to the code sample it follows, and introduced the two orchestrator details by saying when they matter. Structure: - The "Response schema input limitations" note appeared in both the Python and TypeScript tabs. Replaced both with one language-neutral note after the code examples. - The "Stuck JoinNode" caution appeared in all three tabs. Replaced them with one caution after the code examples, stating the rule that every node feeding a join must produce an output. - Moved the unbounded-cycle caution out of the TypeScript tab to the end of the section, since it is not language specific. Snippet header comments got the same wording pass. Verified afterwards: the 26 snippets still type-check, all 53 snippet includes resolve, and every snippet is still semantically identical to samples/workflows/ at adk-v2.0.0.
|
Thanks, changes applied. Wording. Applied every suggestion. Beyond those, I did a pass over all 30 TypeScript tabs for the same problems rather than only the flagged lines:
Same pass over the snippet header comments, including the Notes moved out of the tabs. All three are now single, language-neutral notes after the code examples:
Two things worth your call1. The three JoinNode cautions did not say the same thing. Consolidating them surfaced a behavioural disagreement rather than a wording one. Python: "the JoinNode is stuck and workflow execution stops." The TypeScript one is right for adk-js. In I could not verify the Python or Go runtimes, so I did not want to assert either behaviour for all three languages. The consolidated caution states the actionable rule that holds regardless — every node feeding a join must produce an output — and describes the consequence without claiming a specific mechanism. If the Python and Go statements are accurate for those runtimes, this is a genuine cross-language difference and probably deserves to be documented explicitly; happy to add that if you can confirm the Python side. 2. Definition-list bullets left as they are. Your "fix the other sentences that start with code syntax" note — I read that as prose sentences, not the |
joefernandez
left a comment
There was a problem hiding this comment.
thanks for updates! Approved for publish
What this does
Adds TypeScript coverage to the five graph-workflow pages under
/graphs/.Every section that had a Python tab now has a TypeScript tab, placed
between Python and Go to match the ordering used elsewhere in the repo — 30
tabs in total.
graphs/index.mdgraphs/routes.mdgraphs/data-handling.mdgraphs/human-input.mdgraphs/dynamic.mdThe code lives in 26 new snippet files under
examples/typescript/snippets/graphs/, pulled in with--8<--regionincludes, following the convention already used by the Go snippets and by the
existing TypeScript snippets in
callbacks/,runtime/andagents/.Why the Python tab wasn't enough
The Python examples don't translate line-for-line, so a TypeScript reader had
to guess at several things that differ:
@nodedecorator —node(fn, options)is the factory form, andnew FunctionNode(name, fn, config)the explicit oneSchema), not pydantic modelsctx.state, not returned on an eventcontent;outputis what reaches thenext node
ctx.runNode()resolves to a node result, so you read.outputThe tabs also call out three behaviours that are easy to get wrong and have no
Python counterpart:
ctx.runNode()does not throw when a child interrupts — it resolves withinterruptIdspopulated andoutputstill undefined, so an orchestratorthat doesn't check will decide on an answer the human never gave
outputsilently overwrites the firstLlmAgent.inputSchemais not the node's input contract inside a graph; thevalidating schema belongs on the node via
node(agent, {inputSchema})Provenance of the snippets
These are ports of the runnable samples in
google/adk-jsundersamples/workflows/,which already map 1:1 to the section anchors on these pages and are executed in
that repo's CI (every sample is constructed, and the offline ones run
end-to-end with the model stubbed). So the code here is derived from examples
that are known to run, not written fresh against the docs.
Verification
mkdocs build --strictpasses.with no tab set left without a TypeScript entry.
--8<--references on these pages (Go's 23 + the new 30) resolve to areal file and region; no unresolved directives in the output.
tsc --noEmitwithstrict,noUnusedLocalsandnoUnusedParameters, against the adk-js workflow API.rendered code blocks (verified against the built HTML).
language-support-taglines.Open questions for reviewers
Version label.Resolved.@google/adk@2.0.0is now published, sothe
^2.0.0pin installs and theTypeScript v2.0.0tags are correct. All 26snippets type-check clean under
strictagainst the published package.No CI for TypeScript snippets. Go and Kotlin have
go-snippets-pr-check.yaml/kotlin-snippets-pr-check.yaml, but nothingcompiles the TypeScript ones, so they will rot silently. I'd suggest a
follow-up workflow running
tscacrossexamples/typescript/snippets/*—that would cover the whole tree, not just these pages. Can do it in this PR
or separately, whichever you prefer. (It would be red until point 1 is
resolved, since the package can't install today.)
Notes