Skip to content

feat(tools): port the adk-python v0.1.0 retrieval tools - #854

Open
AmaadMartin wants to merge 6 commits into
google:mainfrom
AmaadMartin:v010-retrieval-tools
Open

feat(tools): port the adk-python v0.1.0 retrieval tools#854
AmaadMartin wants to merge 6 commits into
google:mainfrom
AmaadMartin:v010-retrieval-tools

Conversation

@AmaadMartin

@AmaadMartin AmaadMartin commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator

Ports the tools/retrieval modules from adk-python v0.1.0, additively:
nothing already in adk-js is removed, downgraded or duplicated.

18 files, +1607, −0. core/src/tools/vertex_rag_retrieval_tool.ts is
untouched and not in the diff.

What was missing, and what this adds

v0.1.0 capability adk-js had it? Added
BaseRetrievalTool — the shared one-argument query declaration no core/src/tools/retrieval/base_retrieval_tool.ts
LlamaIndexRetrieval — answers from any object with retrieve no core/src/tools/retrieval/llama_index_retrieval.ts
FilesRetrieval — indexes a directory no core/src/tools/retrieval/files_retrieval.ts
Server-side RAG on Gemini 2 yes, VertexRagRetrievalTool nothing
RAG store config yes, a superset of v0.1.0 nothing

Deliberately not added

  • VertexAiRagRetrieval as a class. VertexRagRetrievalTool already owns
    that job. Adding a second class under another name would be duplication.
  • v0.1.0's flat rag_corpora / similarity_top_k /
    vector_distance_threshold parameters.
    adk-js takes the whole
    VertexRagStore, which also carries ragRetrievalConfig and storeContext.
    Matching v0.1.0 here would remove capability.

Where v0.1.0 and adk-js deliberately disagree

Recorded as explicit DIVERGENCE assertions in the parity test, so the test pins
what adk-js actually does and a future change to it is caught:

Not included: v0.1.0's client-side retrieval path, which gates on
model.startswith('gemini-2') and falls back to a function declaration. Adding
it means an optional constructor argument on VertexRagRetrievalTool; happy to
follow up if wanted.

Interface, side by side with Python

Every public and protected member the port adds, against its v0.1.0 original.

BaseRetrievalTool

adk-python v0.1.0 this PR
class class BaseRetrievalTool(BaseTool) abstract class BaseRetrievalTool extends BaseTool
protected _get_declaration() -> types.FunctionDeclaration _getDeclaration(): FunctionDeclaration

abstract is explicit here because the class supplies no runAsync; Python
leaves that implicit. The declaration body is the same — one required query
string, described identically.

LlamaIndexRetrieval

adk-python v0.1.0 this PR
construction __init__(*, name, description, retriever: BaseRetriever) constructor(params: LlamaIndexRetrievalParams)
field self.retriever readonly retriever: LlamaIndexRetriever
method async run_async(*, args, tool_context) -> Any override async runAsync({args}: RunAsyncToolRequest): Promise<unknown>

Keyword-only arguments become one params object, which is how adk-js tools are
already constructed. retriever is readonly. Its type is a structural
LlamaIndexRetriever rather than llama_index's BaseRetriever, so llamaindex
stays an optional dependency — Python gets the same effect from TYPE_CHECKING.

FilesRetrieval

adk-python v0.1.0 this PR
construction __init__(*, name, description, input_dir), reading the directory and building the index inline static async create(params: FilesRetrievalParams): Promise<FilesRetrieval>
constructor the same __init__ constructor(params: FilesRetrievalConstructorParams), taking an already-built retriever
field self.input_dir readonly inputDir: string

The one interface change worth a close look. SimpleDirectoryReader.loadData
and VectorStoreIndex.fromDocuments are both async in LlamaIndexTS and sync in
Python, so that work cannot run in a constructor. Moving it to a static factory
also lets a caller supply a retriever built some other way.

New exported types, with no Python counterpart

Python refers to llama_index's types under TYPE_CHECKING. TypeScript needs
them declared at exported positions, so they are exported rather than inlined:

LlamaIndexRetriever, LlamaIndexNode, LlamaIndexNodeWithScore,
LlamaIndexRetrievalParams, FilesRetrievalParams,
FilesRetrievalConstructorParams.

Behaviour differing inside a matching signature

adk-python v0.1.0 this PR
progress output print(f'Loading data from {input_dir}') logger.info(...)
empty retrieval retrieve(...)[0] raises a bare IndexError throws an Error naming the tool
optional package absent ImportError from a module-level import an Error naming the package and the install command

Tests

All 3 adk-python v0.1.0 retrieval tests are ported, each keeping the Python
function name verbatim so the original is greppable.

Source: src/google/adk/tests/unittests/tools/retrieval/test_vertex_ai_rag_retrieval.py @ v0.1.0
Port: core/test/tools/retrieval/vertex_ai_rag_retrieval_python_parity_test.ts

Python test @ v0.1.0 Status
test_vertex_rag_retrieval_for_gemini_1_x ported
test_vertex_rag_retrieval_for_gemini_1_x_with_another_function_tool ported
test_vertex_rag_retrieval_for_gemini_2_x ported

v0.1.0 has 3 retrieval tests in total. The other three retrieval test files on
adk-python main did not exist at that tag. Plus 14 new tests for the added
modules, in separate files.

Also included

  • Unit guides, one per class, under docs/guides/tools/retrieval/, with
    docs/guides/README.md as the index. This creates docs/guides/, following
    adk-python's layout.
  • A sample at samples/tools/retrieval/, with a README and the data/
    folder it indexes. That folder holds the same two documents adk-python's
    contributing/samples/integrations/files_retrieval_agent indexes, read by a
    tool of the same name, search_documents. Its two Python-specific statements
    are corrected rather than carried over.

Note tests/integration/docs_samples/docs_samples_test.ts resolves its root to
samples/workflows, so the new samples/tools/ category is type-checked,
linted and licence-checked but never executed. The category README says so.

Verification

Check baseline this branch
ts:check 4 errors same 4 errors
ts:check:samples / lint / format:check / check_license.sh pass pass
docs:check pass pass
retrieval unit tests 17 / 17
docs_samples integration 27 / 27 27 / 27

The 4 ts:check errors are pre-existing Cannot find module '@google/adk-devtools'
in integration fixtures. Every TypeScript snippet in the guides was compiled
against the published types before being included.

The sample, in adk web. Running web samples/tools with nothing
configured: /list-apps returns ["retrieval"], the agent module loads, and
creating a session succeeds. The FilesRetrieval half reports that it is off
and names the command that turns it on, and the agent still starts with
employee_handbook. adk run on the same agent reaches its prompt the same
way. I did not drive a live model turn — this environment has no API key — so
the conversational path rests on the unit tests rather than on a manual check.

Amaad Martin added 4 commits September 3, 2026 11:35
adk-js covers Vertex AI RAG with VertexRagRetrievalTool but has no
general retrieval-tool surface, so a tool that answers a natural-language
query out of a local index has to reimplement the declaration and the
argument contract from scratch. adk-python has carried that surface since
v0.1.0.

Adds the three modules adk-js lacks, ported from adk-python at ref
v0.1.0:

  - BaseRetrievalTool, which fixes the one-argument `query` declaration
    every retrieval tool advertises.
  - LlamaIndexRetrieval, answering with the top node's text. The
    retriever is typed structurally, so llamaindex stays optional
    exactly as the TYPE_CHECKING import keeps it optional in Python.
  - FilesRetrieval, which indexes a directory. Reading and indexing are
    async in LlamaIndexTS where they are sync in Python, so they move
    from the constructor to a static create().

Nothing existing changes. VertexRagRetrievalTool is untouched: its
server-side-only behaviour, its fixed name and its BuiltInTool
registration all stand. The v0.1.0 tests for VertexAiRagRetrieval are
ported alongside as a parity set that records, per assertion, where
v0.1.0's model-gated client-side path differs from what adk-js does
today — the Gemini 1.x function-declaration path, the shared tool entry,
and the toolsDict registration that #789 deliberately added.
Documents `BaseRetrievalTool`, `LlamaIndexRetrieval` and `FilesRetrieval` at
`docs/guides/tools/retrieval/index.md`, mirroring `core/src/tools/retrieval/`.
The three files are one guide rather than three, because a reader choosing
between the implementations has to see them side by side.

The section that earns the guide is the comparison with the pre-existing
`VertexRagRetrievalTool`. The two look interchangeable from the outside and are
not: one extends `BaseTool` and retrieves in your process behind a function
declaration, the other extends `BuiltInTool` and adds a
`retrieval.vertexRagStore` entry so the model retrieves server-side, returning
grounding metadata instead of a function response. The guide gives the reader
the trade-offs — inspectable results and any backend against no extra round
trip — rather than a recommendation.

Every snippet was extracted to a scratch file under `samples/` and compiled
with `tsc -p samples` against the published types, so the signatures, the
`VertexRagStore` fields and the `await FilesRetrieval.create` shape are real.

`docs/guides/README.md` is the index the guide skill requires; it is new, since
adk-js had no `docs/guides/` tree before this change.
Adds `samples/tools/retrieval/agent.ts`, an `LlmAgent` grounded on a
`LlamaIndexRetrieval` tool, plus `samples/tools/README.md` for the new
category.

The sample ships its corpus in the file behind a hand-written
`LlamaIndexRetriever`, which is the honest demonstration of the design: the
retriever is a structural interface and nothing in `LlamaIndexRetrieval`
imports `llamaindex`, so the tool works without the optional dependency. The
`FilesRetrieval` half is real but gated on `ADK_SAMPLE_DOCS_DIR`, because it
needs `llamaindex`, `@llamaindex/readers`, a configured embedding model and a
directory of documents. The header says so where the workflow samples say
`Run (offline, no API key)`, and the category README repeats it with the
install command.

The category README also records what CI does and does not do here:
`tests/integration/docs_samples` resolves `SAMPLES_ROOT` to
`samples/workflows`, so lint, Prettier, the license check and
`ts:check:samples` reach this sample and nothing executes it.

The sample links its guide by relative path rather than an adk.dev URL. Every
adk.dev link in the repository is a `graphs/` section a sample ports, and this
sample ports none.
Two reviewer corrections.

The combined page documented three classes at once. A reader arrives at a guide
from search, not at the set, so a page covering all three cannot tell them in
its first paragraph whether they are on the right one. Each class now has its
own guide, mirroring its source file, and each opens by naming its siblings with
the reason to pick each. The client-side versus server-side comparison lives in
the BaseRetrievalTool guide, because that is where a reader makes that choice;
the other two link to it rather than repeating it. No content was dropped in the
split -- the sections were redistributed.

Samples now carry their own README, following the revised template: overview,
sample inputs, a Mermaid graph, the techniques worth naming, how to run, and the
guides to read next. The category README's single retrieval entry became three.

The sample's header pointed at the combined guide, which no longer exists; it
now points at the LlamaIndexRetrieval guide, the class it is built on.

Every relative link in the new files was resolved against the tree, and both
anchor targets in the FilesRetrieval guide were confirmed to exist. Prettier,
the licence check and `tsc -p samples` are clean.
Amaad Martin added 2 commits September 4, 2026 14:44
…ured

The sample asked for ADK_SAMPLE_DOCS_DIR and a LlamaIndex install before its
FilesRetrieval half did anything, so a reader who cloned it got one tool and a
paragraph explaining the other. Ship three documents beside the agent, default
inputDir to them, and catch the optional-peer-dependency failure so the sample
runs to completion either way.

The guides' "Related samples" links now point at the sample's README rather
than straight at agent.ts, and the README gains a Configuration section
covering both knobs and how to swap in your own corpus.
adk-python has a matching sample, contributing/samples/integrations/
files_retrieval_agent, which indexes a data/ folder of two documents through a
tool called search_documents. Reusing its corpus and its tool name costs
nothing and makes the two samples comparable, which is the point of a parity
port.

The two documents state that ADK is a Python framework and that function tools
are Python functions. Both are corrected here rather than carried over; the
retrieval section also gains the two classes this port adds.
@AmaadMartin

Copy link
Copy Markdown
Collaborator Author

Final look, and one CI note.

run-tests (windows-latest) is red, and it is not this PR. The same job fails on main right now — daad4db4a and 1a699f4e1, the two most recent commits. On main two suites fail; on this branch one does, and it is the same one:

FAIL  integration  tests/integration/a2a/stream/stream_test.ts > A2A: RemoteAgent Streaming
      Error: CLI exited prematurely with code 1

It is a harness failure, not an assertion: the test spawns a CLI subprocess and the subprocess dies on Windows. Nothing in the diff touches A2A, streaming, or process spawning. The run's own numbers say the same thing — 4112 tests passed, 0 failed, one suite failed to start.

Every other check is green, including run-tests on ubuntu and macos.

State of the PR. 18 files, +1607, −0.

  • Three inline comments fixed, each answered in thread.
  • Sample runs unconfigured, verified in adk web with a screenshot on Integrate OpenTelemetry (OTel) support #10.
  • Interface side-by-side added to the description, per class.
  • data/ and the search_documents tool name now match adk-python's files_retrieval_agent.

Nothing outstanding from me. Merge when you are happy.

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