Get desktop application:
View/edit binary Protocol Buffers messages
InteractionEventService records UI interactions that do not mutate the artifact itself. The binding and method name are taken from the production JavaScript descriptor for HpN0Ub.
LogInteractionEventRequest is the HpN0Ub request. The UI uses distinct positional event fields for different artifact interactions; each carries the affected artifact ID in a one-element message.
Guidebook operations
Service definition
Source operations
ActOnSourcesRequest is the yyryJe chat-query request shape observed in four captures. It is not the legacy three-argument action-verb shape.
Fields 3 through 7 are null in observed requests.
ActOnSourcesResponse carries the observed numeric response value. Its semantics are unconfirmed.
Source registration for Resumable Upload (rpc.go:31) Request shape, captured from api.Client.registerFileSource (internal/notebooklm/api/client.go:952): [[[filename]], project_id, [2], [1, null × 9, [1]]] The arg_format directive cannot express the deeply-nested wrapper; a custom encoder lives at api.Client.registerFileSource. Returns the server-assigned source_id at response position [0][0][0].
AddFileSource (o4cbdc): register an uploaded file as a notebook source. HAR-verified across two pdf-upload captures (2026-04-19, pdf-upload/, pdf-upload-new/) — both byte-identical for the trailing options blob. Wire request: [[[filename]], project_id, [2], [1, null × 9, [1]]] Position [0] is a 2-level-nested filename list (the inner [filename] is a 1-element list). Position [2] is [2] = source_type=file_upload. Position [3] is the same fixed options blob seen in DeleteArtifact's V5N4be call. See api.Client.registerFileSource (client.go:952).
Wire response (HAR-verified): [[[[source_id], filename, [null, null, null, null, 0]]], null, [[[[source_id], filename, [null, null, null, null, 0]]]]] Positions [0] and [2] both echo the assigned source row; [1] is always null in the captured calls. The inner metadata list at position [2] of each row is [null × 4, status_int=0]. We surface the source_id only.
AddSources (izAoDd). HAR (more-requests3) shows the reply is a list containing the same Source descriptor LoadSource (hizoJc) returns: [ [source_id], title, [source_metadata], [null,2], ... ] not a Project envelope.
Update existing request messages to match Gemini's findings
AddSourcesResponse is the izAoDd response envelope: [[source, ...]].
BulkImportFromResearch (rpc.go:73). 5-position polymorphic variant of LBwxtb that imports a batch of URL+title pairs from a research session. HAR-verified 2026-04-17 against notebook 00000000-0000-4000-8000-000000000006, conversation 00000000-0000-4000-8000-000000000401, ten URL sources. Request shape (api.bulkImportArgs at client.go:5102): [null, [1], conversation_id, project_id, [source_1, ..., source_N]] Each source tuple is 11-position; encoded by Go helper because arg_format cannot represent the inner [null, null, [url, title], null × 7, 2] tuple shape.
BulkImportFromResearch (LBwxtb, 5-position polymorphic variant). Wire shape: [null, [1], conversation_id, project_id, [source_1, ..., source_N]] HAR captures show two distinct per-source tuple shapes selected by position [10]: URL import (api.bulkImportArgs at client.go:5102, source_type=2): [null, null, [url, title], null × 7, 2] Note/text import (HAR-observed in NotebookLM web UI capture, 2026-04-23, importing a 3.4kB markdown research report, source_type=3): [null, [title, content_markdown], null, 3, null × 5, 3] The Go side currently encodes only the URL variant; the note variant is a follow-up. BulkImportSourceInput carries enough fields to model both — content stays empty for URL imports, url stays empty for note imports.
BulkImportFromResearchWireRequest is the positional note/text import form observed from the web UI. The live URL-import API keeps its logical request type and custom encoder above.
CancelDiscoverSourcesJob (Zbrupe). Cancels an in-flight DiscoverSources / DiscoverSourcesAsync / DiscoverSourcesManifold job. JS-bundle-verified; no HAR yet. TODO(har): trigger by canceling a running fast-research / deep-research / discover-sources flow before completion.
CancelDiscoverSourcesJob (Zbrupe).
CancelGeneration (XgrPMd). The captured request has a null leading placeholder followed by the generation identifier. The server returns an empty array on success.
CancelGeneration (XgrPMd).
(message has no fields)
CopyProject (te3DCe). Duplicates an existing notebook (sources, artifacts, settings) into a new project. Response HAR-observed as a single status int [3]; not consumed by any live caller.
CopyProject (te3DCe). Duplicates a notebook.
CopyProjectResponse is the te3DCe reply. HAR-observed as a single int [3]; modeled as a status/state code (the copy operation's result). The earlier declared Project return type was an unverified guess and did not match the wire.
Artifact operations
Audio operations
e.g. "en"
CreateAudioOverview (AHyHrd). The legacy audio-overview creator. The production surface now goes through CreateUniversalArtifact (R7cb6c with kind=2), but a direct AHyHrd path is still wired in api.Client.createAudioOverviewDirectRPC (client.go:1407) as a fallback. JS-bundle-verified; HAR-observed under that fallback.
CreateAudioOverviewLegacy (AHyHrd). Direct-RPC fallback that api.Client.createAudioOverviewDirectRPC still uses; the live UI now goes through R7cb6c. The "Legacy" suffix avoids a name collision with the modern CreateAudioOverview rpc that targets R7cb6c above.
CreateLabel / MutateLabel / DeleteLabels — write companions to GetLabels (I3xc3c). All three are bound by the JS bundle but no HAR has been captured yet; trigger by interacting with the labels affordance in the source-list UI.
CreateLabelRequest is the manual-label form of agX4Bc. It also creates a collection, with scope 3 and a null project_id; a collection create may seed the new collection with member notebooks.
Fields 3 through 5 are null in observed requests.
Observed only as 3, on requests that create a collection. See GetLabelsRequest.scope.
Note operations
CreateNoteRequest also carries the rich-note payload the web UI sends when it saves a note with formatting: grounding details at field 4 and the structured document at field 6, the same two slots the response returns them in. These are decode-only. This RPC's arg_format passes literals rather than the request's own fields, because the live path allocates an empty shell and then fills it in through MutateNote, so nothing here reaches the wire.
The request carries the grounding records bare at this position, unlike the response, which wraps them in one more array layer (NoteGroundingDetails). Same element type either way.
CreateNoteRichRecord is the CYK0Xb response tuple. It is NoteRecord plus the two rich-note slots: the same grounding-details list and structured document GetNotesRichRecord carries, in the same positions. NoteRecord itself cannot model them because it lives in notebooklm.proto, which this file imports rather than the other way around. Only note_id is read by the live CreateNote path, which allocates a shell and then fills it in through MutateNote; the remaining fields are decode-only.
Project operations
Request messages reconstructed from captured batchexecute traffic.
Decode-complete binding for the polymorphic R7cb6c request envelope.
Semantics unconfirmed. Observed as [1] on a slide request.
Video operations (uses same R7cb6c RPC as audio but with mode=3)
Video overview request (uses same R7cb6c RPC as audio, but with mode=3 parameter)
Content style (only BRIEF=2 observed so far)
Visual presentation style
e.g. "en"
Wire format: [%context%, null, %project_id%] Polymorphic endpoint shared with PollDeepResearch
DeleteChatTurns is the inferred bundle name for J7Gthc. Captured requests confirm the wire shape and conversation ID; field 4 semantics remain unknown.
DeleteChatTurns is inferred from the bundle binding and the fact that J7Gthc fires before feedback. The observed wire has four positions.
Field 3 is null in observed requests.
semantics unconfirmed
(message has no fields)
DeleteDeepResearch (rpc.go:72). Soft-delete a research session; server transitions state 2 -> 5 (the row is retained, future poll queries skip state=5). HAR-verified 2026-04-17. Polymorphic with BulkImportFromResearch: same LBwxtb id, server discriminates on arg-4 presence (delete = 4-position, bulk-import = 5-position). Request shape (api.deleteDeepResearchArgs at client.go:5034): [null, [1], conversation_id, project_id]
DeleteDeepResearch (LBwxtb, 4-position polymorphic variant). Wire shape: [null, [1], conversation_id, project_id]
empty array on success
(message has no fields)
DiscoverSources (Es3dTe). Per the JS bundle binding to /LabsTailwindOrchestrationService.DiscoverSources. The previous rpc_id "qXyaNe" was a speculative inference that does not match any JS bundle entry or HAR capture; corrected to Es3dTe. No HAR yet for the wire shape. arg_format below is a likely shape based on sibling RPCs but is unverified — TODO(har): capture by triggering "Discover sources" from the source-add UI. Note: the related research-flow RPCs (Ljjv0c, QA9ei, e3bVqc, LBwxtb) are bound by the JS bundle to DiscoverSources*-family names (DiscoverSourcesManifold, DiscoverSourcesAsync, ListDiscoverSourcesJob, FinishDiscoverSourcesRun); the "research" feature is layered on top of the DiscoverSources job system.
ExecuteWritingFunction (likKIe). In-document writing assistant — rewrite, expand, summarize a selection inside an artifact. JS-bundle-verified; no HAR. TODO(har): trigger from the artifact editor's writing toolbar.
ExecuteWritingFunction (likKIe). In-document writing assistant.
e.g. "rewrite", "expand", "summarize"
ExportToDrive (Krh3pd). Pushes notebook artifacts to the user's Drive. JS-bundle-verified; no HAR yet. TODO(har): trigger by clicking "Export to Drive" on a notebook.
ExportToDrive (Krh3pd). wire shape unverified.
FetchInteractivityToken (rpc.go:50). Voice-session auth + ICE server config for the WebRTC interactive-audio mode. Request is the empty payload []. Response is a positional JSON envelope whose [0] field is a JSON-encoded string carrying {lifetimeDuration, iceServers, blockStatus, iceTransportPolicy}. See internal/interactiveaudio/signaling.go:36 and the existing FetchInteractivityTokenRequest/Response messages at line 858+.
FetchInteractivityToken (Of0kDd). HAR-verified (docs/captures/notebooklm.google.com.jsonl:24, 2026-04-06). Request is the empty payload []. Response is a 1-element JSON array whose [0] entry is a JSON-encoded string carrying the WebRTC bootstrap blob: lifetimeDuration, iceServers (STUN+TURN credentials), blockStatus, and iceTransportPolicy. Decoded by interactiveaudio.parseInteractivityTokenResponse (signaling.go:72) which JSON-unmarshals the inner string into a Go-side InteractivityToken struct that mirrors these fields.
e.g. "86400s"
e.g. "NOT_BLOCKED"
e.g. "all"
GenerateAccessToken (preRPe). Per-session token mint — likely used by embed widgets or third-party surfaces that need a short-lived credential. JS-bundle-verified; no HAR.
GenerateAccessToken (preRPe) has an empty request and returns [oauth_token, [relative_ttl_seconds], [scope, ...]].
(message has no fields)
GenerateArtifact (Rytqqe). Distinct from CreateArtifact (xpWGLf) and CreateUniversalArtifact (R7cb6c). Captured requests carry a context envelope followed by an artifact ID. The operation name is inferred from the bundle; the server-side effect is unconfirmed.
GenerateArtifact (Rytqqe) — distinct from CreateArtifact (xpWGLf) and CreateUniversalArtifact (R7cb6c). The operation name is bundle-derived; captured requests prove only the context and artifact ID positions.
GenerateArtifactSuggestions / AudioTopicSuggestions (rpc.go:133). The web UI calls this before R7cb6c (CreateUniversalArtifact) to get a list of AI-generated topic blueprints. Wire format verified against HAR (create-audio, 2026-04-14): [[kind], project_id, [[src1], [src2], ...], variation] Only audio (kind=2) is HAR-verified; video and slide kinds are not covered. The variation int re-rolls suggestions (1, 2, 5, 6 observed). See internal/method/labs_tailwind_artifact_suggestions.go.
GenerateArtifactSuggestions / AudioTopicSuggestions (otmP3b). HAR-verified for kind=2 (audio) via the create-audio capture used for internal/method/labs_tailwind_artifact_suggestions.go (filed 2026-04-14; not present in this repo's docs/captures/ but the encoder is the durable record). Wire request: [[kind], project_id, [[src1], [src2], ...], variation] Wire response: [[[title, description], [title, description], ...]] Each call returns three suggestion pairs. variation is a re-roll seed (1, 2, 5, 6 observed); the UI bumps it on every "refresh" click. Video and slide kinds are not yet HAR-verified.
re-roll seed
Field 5 is null when prompt is present.
GenerateDocumentGuides (rpc.go:82). Per-source guide RPC: the wire call is keyed by source_id with a 4-level-nested arg shape [[[[source_id]]]] that the arg_format template cannot express. Invoked via api.Client.GenerateSourceGuide (client.go:3010); response is [[[null, [summary], [[topic, ...]], []]]]. The request message exists at line 709 (GenerateDocumentGuidesRequest).
Generation operations Per-source guide generation (tr032e) is not declared here; the wire call is keyed by source_id with a 4-level-nested arg shape that the [%project_id%]-style arg_format cannot express. It's invoked directly via rpc.Do in the api package (see api.Client.GenerateSourceGuide).
The gRPC-Web endpoint still expects a manually constructed JSON array, but this message mirrors the observed request state on that wire: [ [[[source_ids]]], prompt, history, [mode, null, citation_modes, follow_up_modes], conversation_id, draft_response_id, parent_response_id, notebook_id, sequence_number ]
chunk preserves the cumulative answer text used by existing callers.
is_final mirrors the completion flag at response position [4].
Decode-complete positional binding for captured gRPC-Web request and response frames. The logical method above remains the live API surface.
Field 6 is null in observed requests.
captured opaque status code; meaning unconfirmed
Guide identifier (UUID).
GenerateReportSuggestions (ciyUvf). HAR-verified; see internal/method/LabsTailwindOrchestrationService_GenerateReportSuggestions_encoder.go. GHsKob is a legacy/predecessor id for the same logical RPC. It does not appear in the current JS bundle (boq_labs-tailwind-frontend) and has no observed wire traffic. Treat GHsKob as dead; ciyUvf is the live id.
GetArtifact (v9rmvd) was captured from the live rendering path 2026-07-27. The earlier BnLyuf id was a different, unreachable inference that returned 400. The request uses [artifact_id, context]. The Artifact response carries type-specific fields, including type-4 app data.
GetArtifactRequest is [artifact_id, context].
GetArtifactUserState (ulBSjf). Read companion to UpsertArtifactUserState (Fxmvse). Both are bound by the JS bundle to /LabsTailwindOrchestrationService.GetArtifactUserState. No standalone HAR observed: the read path is rolled into the gArtLc (ListArtifacts) response — each artifact tuple already carries the saved ArtifactUserState inline at a late field position (the same [[[seconds, nanos]]] shape that Fxmvse upserts). The dedicated ulBSjf read is reserved for hosts that need the per-artifact value without re-listing. TODO(har): capture a direct ulBSjf request to confirm the request body shape; the read response is expected to mirror UpsertArtifactUserStateResponse (a single ArtifactUserState).
GetArtifactUserState (ulBSjf). Read companion to UpsertArtifactUserState (Fxmvse). No HAR observed for the dedicated read path: the value is also returned inline by gArtLc (ListArtifacts) as part of each artifact tuple, and the UI reads it from there. The fields below mirror the HAR-verified write side; the request likely sends only the artifact_id, and the response is expected to wrap a single ArtifactUserState the same way as UpsertArtifactUserStateResponse. TODO(har): capture a standalone ulBSjf request to confirm.
GetAudioFormats (rpc.go:89). HAR-verified against captured traffic. Request payload observed verbatim: [[2, null, null, [1, null × 9, [1]], [[1,4,8,10,2,3,6,9]]], null, 1] Returns the audio-overview style menu (Deep Dive, Brief, Critique, Debate). The opaque inner [1, null × 9, [1]] and ordering vector [[1,4,8,10,2,3,6,9]] are bytes captured verbatim; semantics not yet decoded.
GetAudioFormats (sqTeoe). HAR-verified against 11+ captures (notebooklm.google.com.jsonl, 2026-04-19..2026-04-23). Returns the full create-artifact menu — audio styles, video styles, slide styles, AND the prebuilt briefing-doc/study-guide templates. The request is a fixed-sentinel payload (no varying fields), so it has no arg_format. The same RPC powers every "create X" picker the UI shows.
Wire shape: [[2, null, null, [1, null × 9, [1]], [[1,4,8,10,2,3,6,9]]], null, 1]
Field 2 is null in observed requests.
observed 1
Response shape (HAR-verified): four positional entries, each itself wrapped in an extra array layer: [ [<audio_kinds>], // [[id, name, description], ...] [<video_kinds>], [<slide_kinds>], [<doc_templates>], // [[title, subtitle, system_prompt], ...] ] audio/video/slide kinds share the AudioFormat shape; doc templates use the distinct DocTemplate shape. The extra wrapping layer is modeled with one-field list-wrapper messages so a present-but-empty kind round-trips as [] rather than null.
Opaque pagination/resume cursor returned after the message list.
Conversation lifecycle
Wire format: [%context%, null, %project_id%, %limit%]
Each conversation id arrives wrapped as ["uuid"].
GetDeepResearchSessions (rpc.go:71). Polymorphic with DeleteChatHistory: same e3bVqc id, server discriminates on request payload shape. The deep/fast-session list call uses [null, null, project_id] (api.Client.pollResearch at client.go:4758). Returns ALL deep + fast sessions for the notebook; the caller scans by (research_id, mode=5) for deep or (conversation_id, mode=1) for fast.
GetDeepResearchSessions (e3bVqc, polymorphic with DeleteChatHistory). Wire shape: [null, null, project_id] Response is a list of deep+fast research sessions; clients filter by (research_id, mode=5) for deep or (conversation_id, mode=1) for fast.
GetLabels (I3xc3c). JS bundle binds this to /LabsTailwindOrchestrationService.GetLabels. HAR-verified across 8+ NotebookLM web UI captures (2026-04-23). Returns the notebook's labels (a.k.a. autolabel/source-grouping clusters): per-label tuples carrying a label, a member source list, and a server-assigned group UUID. Most notebooks return [] (no labels computed yet). Notebooks where the user has invoked autolabel return populated entries. Wire request: [[2], project_id] [0] = [2] is an opaque mode/operation enum (constant across all captures); semantics not yet decoded. Wire response: [] OR [[label, [[src_id], ...], group_uuid, ""], ...] Earlier rounds of this proto called this method GetSourceGroups — the canonical service name (per JS bundle) is GetLabels, and the related operations CreateLabel (agX4Bc), MutateLabel (le8sX), and DeleteLabels (GyzE7e) confirm the labels framing.
GetLabels (I3xc3c). HAR-verified label/autolabel query. The notebook UI fires this on every notebook load to render the source-list section headers; an empty response means the user hasn't yet computed labels for this notebook. GetLabelsRequest carries a trailing scope selector. In the notebook scope the field is absent and project_id names the notebook; in the collections scope the field is 3 and project_id is null, because collections are account-scoped rather than notebook-scoped.
Observed only as 3, on requests that read collections. Other values may exist; the numbering is not confirmed to be an enum, so it is kept as a plain int rather than named.
GetLabelsResponse returns rows at a slot that depends on the request scope: field 1 in the notebook scope (13 observed responses) and field 2 in the collections scope (2 observed responses). The row shape is identical, so both are modeled as Label.
GetMagicView (rtY7md). Read companion to GenerateMagicView (uK8f7c). JS-bundle-verified; no HAR. TODO(har): trigger by opening a previously-generated Magic View.
GetMagicView (rtY7md). The captured request is [project_id] and the response is a single opaque status code. Its enum meaning is unconfirmed.
Field 2 is null in observed requests.
GetNotesRichWireResponse is the keyed response shape returned by cFji9. The response-side note record differs from the public Note message: rich_text is either a legacy string or a structured RichDocument, and field 4 repeats the document's grounding details without their source-id keys.
Account operations
Account management
Field 2 is null in observed requests.
Field 4 is null in observed requests.
Analytics and feedback
ListArtifactsRequest wire (HAR-verified, more-requests2): [<RequestContext>, project_id, "<filter>"] where RequestContext.artifact_types carries the type filter and field 3 is a CEL-ish filter string (e.g. NOT artifact.status = "ARTIFACT_STATUS_SUGGESTED"). The live api.Client.ListArtifacts hand-builds a truncated [[2], project_id] form and does not use this message as an encoder.
ListExpertIntelligenceContent (mVtEUb). Curated featured-content surface. Captured requests use [context, 1]; the second value's semantics are not yet established.
ListExpertIntelligenceContent (mVtEUb). Curated featured surface.
ListModelOptions (EnujNd) has a captured RequestContext request. The captured responses are empty, so option rows remain unmodeled.
ListModelOptions (EnujNd) is captured as [[version, null, surface, caps]].
ListRecentlyViewedProjectsRequest has two captured wire variants. The live command uses the short [null, 1, null, [2]] form. Full web requests carry [project_id, null, context, null, 0, filter]; older full requests instead put context at field 4 and page 1 at field 2.
observed 1
observed 0
LoadSource (hizoJc) returns a Source descriptor and loaded content. The HAR (more-requests3) source shape is [ [source_id], title, [null, status, [added_ts], [origin_source_id, [origin_ts]], type, null, 1, null, byte_size, null×5, [indexed_ts], null×4, mime_type], [null, 2], null, download_url, viewer_url, ... ] AddSources (izAoDd) returns the same descriptor inside a list.
LoadSourceResponse is the hizoJc response envelope: [source, null, null, [loaded content]].
LogEvent / GetPromoCampaign (rpc.go:98). The constant in rpc.go is labelled "LogEvent" but HAR evidence (notebooklm.google.com.jsonl hits across 12+ captures spanning 2026-04-19..2026-04-23) shows it is actually a promo/upsell-card placement lookup. The web UI fires it once per page load. Request shape: [[[[null, "1", 627], [null × 9, [null, null, 2]], 1]]] The middle-positional 627 looks like the campaign/promo slot ID; "1" is locale or surface; the [null, null, 2] tail is opaque. Response carries the upsell card payload (icon URL, title, CTA link, the user's tier — e.g. "NOTEBOOKLM_TIER_PRO_CONSUMER_USER"). The Go side does not call this RPC; it is documented here so the proto matches what the wire actually does.
LogEvent (ozz5Z) is a misnomer per rpc.go's constant; the wire RPC is actually a promo/upsell-card placement lookup. HAR-verified across 12+ captures (notebooklm.google.com.jsonl, 2026-04-19..2026-04-23). Wire request: [[[[null, "1", 627], [null × 9, [null, null, 2]], 1]]] 627 is the campaign/slot id (constant across all captures); "1" is locale/surface; the [null, null, 2] tail at position [9] of the inner array is opaque. The whole request is a fixed sentinel — the only varying byte is the f.sid, which lives outside the f.req body. No Go caller invokes this RPC today; the message exists so future regenerated stubs match the wire reality rather than the rpc.go label.
Wire response is a repeated array of log-event acknowledgements, one per logged event in the request (observed: always exactly one). Captured layout (HAR-verified across 5 captures, all structurally identical modulo tracking IDs): [[[ [null, "1", 627], // slot [[2230, [null × 9, [[null, "NotebookLM icon", "edit"], [[[null, null, "<settings_url>"], false], null, null, "Manage subscription", null, "Manage subscription", null, null, [<click_event>]]], null × 10, [<impression_event>]], null, 2351, 2351, 2230, "NOTEBOOKLM_TIER_ULTRA_LIGHT_CONSUMER_USER", null, null, false, []]], 0]]] The outer-outer [ ] is the repeated wrapper (LogEventResponse itself); each element is a PromoLogEntry. user_tier (PromoCard field 7) is the only durable, human-meaningful field; everything else is rendering/impression-tracking chrome, but is modeled fully so the response round-trips losslessly.
MutateLabelRequest wire (HAR-verified, more-requests2): [<RequestContext>, project_id, label_id, [<mutation>]] The live path (api.Client.mutateLabel) hand-builds these args and does not use this message as an encoder, so the layout is decode-only. The mutation block has two observed inner shapes: [[name, emoji]] (rename/emoji) and [null, [[source_id]]] (attach source); the captured request is the latter.
Observed only as 3, on requests that mutate a collection. See GetLabelsRequest.scope.
MutateLabelsModeRequest is the mode form of agX4Bc. Mode 0 labels previously-unlabeled sources; mode 1 relabels all sources.
Fields 3 and 4 are null in observed requests.
Field 1 is null in observed requests.
PollDeepResearch is the job-handle variant of e3bVqc. It returns the same session shape as GetDeepResearchSessions, but a successful 2026-07-23 CLI capture shows a standard context envelope and a handle in position two: [context, null, job_handle].
PollDeepResearchRequest is the job-handle e3bVqc variant.
PollDeepResearchResponse is the job-handle e3bVqc result envelope.
Needed for source-path URL param.
ReportContent. User-initiated abuse/safety report. The JS bundle binds the live ReportContent endpoint to OmVMXc; the historical rJKx8e id never surfaced in any HAR capture or in the bundle, so it is treated as stale (kept as RPCReportContentLegacy for compatibility, no proto entry). TODO(har): no rpcids=OmVMXc seen in any capture under the current web-UI corpus. To capture: open an artifact, click the kebab menu -> "Report", fill the dialog, submit. The placeholder fields are speculative.
ReportContent (rJKx8e): user-initiated abuse/safety report. wire shape unverified; capture HAR before encoding
wire shape unverified; capture HAR before encoding
wire shape unverified; capture HAR before encoding
(message has no fields)
ReviseArtifact (rpc.go:131). Re-runs an artifact generator with a free-form revision instruction. The response is the revised Artifact row, including type-specific edit instructions when the revision remains pending.
ReviseArtifact (KmcKPe): revise an artifact with instructions. wire shape unverified; capture HAR before encoding
SDPExchange (rpc.go:51). WebRTC SDP offer/answer exchange for the interactive-audio voice session. Request payload is a single string holding {"sdp": "...", "type": "offer"} JSON; the server returns the answer SDP wrapped the same way. See internal/interactiveaudio/signaling.go:52.
SDPExchange (eyWvXc): WebRTC SDP offer/answer exchange. HAR-verified (docs/captures/notebooklm.google.com.jsonl:25, 2026-04-06) — request args = [json_str] where json_str is `{"sdp":"...","type":"offer"}`. Response is `[json_str]` where json_str is the answer SDP wrapped the same way, with `"type":"answer"` and an active fingerprint. Encoded/decoded by interactiveaudio.exchangeSDP (signaling.go:52). The wire keeps the SDP as an opaque JSON-encoded string blob; this proto exposes the decoded sdp+type pair for callers that prefer structured access.
Raw JSON string sent on the wire — kept as a string because the server treats it opaquely and round-trips byte-for-byte.
StartDeepResearch is the legacy request variant retained for generated client compatibility. New callers use StartDeepResearchWire below.
StartDeepResearch is the legacy QA9ei request model. The live client uses StartDeepResearchWire, which adds the observed request context at position zero and leaves position one null. Both responses are [research_id, conversation_id].
StartDeepResearchWire is the canonical QA9ei request. A successful 2026-07-23 CLI capture verified its shape exactly: [context, null, [query, 1], 5, project_id]
Field 2 is null in observed requests.
(message has no fields)
Research operations StartFastResearch — HAR-verified 2026-04-17 against notebook 00000000-0000-4000-8000-000000000006 (rpc.go:68). Request shape (api.startFastResearchArgs at client.go:4587): [[query, 1], null, 1, project_id] Response is a one-element array: [conversation_id]. Mode enum at position [2] is 1 for fast (5 for deep, see StartDeepResearch).
StartFastResearch (Ljjv0c): kick off a fast-research session. Wire shape verified by api.startFastResearchArgs (client.go:4587), against notebook 00000000-0000-4000-8000-000000000006, query "har harl file formats" (NotebookLM web UI capture, 2026-04-17). No HAR copy in this repo's capture set. JS bundle binding: Ljjv0c → DiscoverSourcesManifold. The "research" feature is built on top of the DiscoverSources job system; api.Client uses the StartFastResearch alias. Wire request: [[query, 1], null, 1, project_id] Wire response: [conversation_id] Mode int at position [2] is 1 for fast, 5 for deep. The trailing 1 at position [0][1] is opaque (same byte the deep variant carries).
(message has no fields)
Fields 4 and 5 are null in the observed request.
UpdateFeaturedNotebookStatus (DemIHe). Admin/internal. Fired only by the featured-notebook curation surface. JS-bundle-verified; unlikely to ever be exercised by an end-user account.
UpdateFeaturedNotebookStatus (DemIHe). Admin-only.
UpdateProjectUserState (LQhfEb). Per-user notebook state — last-viewed-at, pinned, hidden, etc. The response is not Empty: the wire carries a nested result message ([null, 2]) at field 2. TODO(har): request wire shape still unverified; capture before encoding.
UpdateProjectUserState (LQhfEb). wire shape unverified. UpdateProjectUserStateRequest wire (HAR-verified, more-requests2): [<RequestContext>, project_id, [null, [null, 2]], [["<state_key>"]]] Field 3 carries the new state value (a nested [null, 2] message); field 4 is the list of state keys being updated (e.g. "notebook_lm_state.saved_source_panel_view").
UpdateProjectUserStateResponse: the wire carries a nested result message at field 2 ([null, [null, 2]]), not an empty envelope.
UpsertArtifactUserState (Fxmvse). JS bundle binds this to /LabsTailwindOrchestrationService.UpsertArtifactUserState. The companion read RPC is GetArtifactUserState (ulBSjf). HAR-verified 2026-04-25 against NotebookLM web UI interactive-audio capture set (22 samples). The web UI fires this every ~5s during interactive audio-overview playback to persist the listener's playback position. The request body is [%context%, %artifact_id%, %state%] where state encodes a single PlaybackPosition (seconds + nanos) wrapped as [[[seconds, nanos]]] — see ArtifactUserState below.
UpsertArtifactUserState (Fxmvse). HAR-verified 2026-04-25 against NotebookLM web UI interactive-audio capture set (22 samples; web UI fires this every ~5s during interactive audio-overview playback to persist the listener's playback position). Wire request: [%context%, %artifact_id%, %state%] - context: standard project_context request envelope - artifact_id: UUID of the artifact (audio overview) - state: ArtifactUserState — encodes [[[seconds, nanos]]] The same ArtifactUserState value is also emitted inline in each gArtLc (ListArtifacts) artifact tuple at a late field position; that inline copy is what the UI reads on page load.
UpsertArtifactUserStateResponse echoes the persisted state. Wire response: [[[[seconds, nanos]]]] — a single ArtifactUserState value (which is itself [[[seconds, nanos]]]) wrapped at field 1.
Service definitions
CreateAccessRequest (n3dkHd). Sent when a non-collaborator opens a shared notebook URL and clicks "Request access". JS-bundle- verified; no HAR yet. TODO(har): trigger by opening a private share link from a logged- in account that lacks access.
CreateAccessRequest (n3dkHd). Sent when a non-collaborator opens a shared notebook URL and clicks "Request access". wire shape unverified.
Project sharing
GetProjectDetailsRequest. JS bundle confirms the canonical service name: JFMDGd → /LabsTailwindSharingService.GetProjectDetails. The Go-side field name `share_id` is historical; HAR shows the wire accepts the project_id (not a share-link slug). Captured against 12+ notebooks in NotebookLM web UI captures (2026-04-06..2026-04-23). Wire request: [project_id, [2]] [1] = [2] is an opaque mode flag (constant across all observed calls); other modes might surface different response payload shapes but have not been observed.
Field is named share_id for backwards compatibility with existing Go callers (api.Client.GetProjectDetails); on the wire this is the project UUID.
ProjectDetails is the JFMDGd (GetProjectDetails) reply. HAR-verified wire shape (fields 1..8 map to positions [0]..[7]): [ [<user_entry>, ...], // [0] collaborators (owner first) <flags|null>, // [1] [true,true] when fully public, null o/w 1000, // [2] opaque limit true, // [3] null, // [4] null, // [5] [3, true, true], // [6] permissions blob false, // [7] ] User entry: [email, role_int, [], [display_name, avatar_url]] role_int 1 = OWNER (the only role observed in single-user captures). The live path decodes this through the generated message and projects only OwnerName + IsPublic. printShareDetails (main.go) reads OwnerName/IsPublic/ProjectId/Title/Emoji/SharedAt/Sources by name. Those Go-named fields are retained below at high numbers (they are not on the wire) for the public projection; the wire fields carry the actual HAR positions for betool/beprotojson decode.
Wire positions.
[0]
[1] visibility flags
[2] opaque, observed 1000
Meaning unconfirmed; true in every observed response.
[4], [5] are null in observed captures; left unmodeled.
[6] [3, true, true]
Meaning unconfirmed; false in every observed response.
Not on the wire; populated by the hand-parser and read by the printer. Kept at high numbers to preserve the Go field names live code uses.
hand-parsed from the owner entry's name
hand-parsed from the flags array
Used in:
Used in:
Account: [account_id, limits, settings, unknown_4, unknown_5]. Field 2 was previously modeled as an "email" string, but the wire carries a [tier, notebook_limit, source_limit, upload_limit, tier] quota array instead (see AccountLimits; confirmed against the hand-written AccountStatus decoder in internal/notebooklm/api/account.go, which reads the same ZwVcOc response positionally). No live code reads Account.email, so the field is replaced rather than kept alongside the real shape.
Used as response type in: LabsTailwindOrchestrationService.GetOrCreateAccount, LabsTailwindOrchestrationService.MutateAccount
[3] observed [[1]]; code meaning unconfirmed
[4] observed [true,1,3,6,true]
AccountBanner is the Account field 5 message: [true, 1, 3, 6, true]. Meaning of the individual fields is not yet confirmed.
Used in:
Descriptive positional names only; individual meanings are unconfirmed.
AccountFlags is the Account field 4 message: [[1]], a single repeated int64 field.
Used in:
individual code meanings unconfirmed
AccountLimits is the [tier, notebook_limit, source_limit, upload_limit, tier] quota array at Account field 2. Position 1 and 5 both carry the same tier value in observed captures.
Used in:
Used in:
Field 3 ([2]) is null in observed captures; left unmodeled. Meanings of the three preference flags are unconfirmed.
[4] observed [null,null,null,[[2,2,1]]]
Field 6 ([5]) is null in observed captures; left unmodeled.
Field 8 ([7]) is null in observed captures; left unmodeled.
AccountSettingsDetail is the nested message at AccountSettings field 5: [null, null, null, [[2,2,1]]]. Only field 4 (a repeated AccountSettingsRule) is populated in observed captures.
Used in:
Fields 1-3 ([0]-[2]) are null in observed captures; left unmodeled.
[3] observed [[2,2,1]]
AccountSettingsRule is a [2, 2, 1] positional triple within AccountSettingsDetail.rules. Meaning of the three integers is not yet confirmed.
Used in:
Used in:
Present empty text is distinct from an omitted field on the wire.
ActOnSourcesOptions carries numeric selectors. Their semantics are unconfirmed; all observed values are 2.
Used in:
ActOnSourcesPromptHistory is the prompt and prior-turn rows in the observed chat-query shape. The numeric field's semantics are unconfirmed.
Used in:
Observed as a string; semantics are unconfirmed.
Used in:
Used in:
Real-time text transcript of user's speech
Real-time text transcript of AI host's speech
Text-to-speech lifecycle hooks
Audio payload transmission triggers
Control frame observed in live captures
Client-side media playback state sync
Microphone active/muted state sync
Connection diagnostics and state updates
AgentCommsPayload reconstructs the typed DataChannel payload at field 4. The sub-field numbers match AgentCommsMessageType values.
Used in:
AgentCommsUserMessage is the protobuf transmitted over the WebRTC DataChannel for real-time bidirectional UI and transcript synchronization.
Field 4 carries the typed event payload observed in live captures.
Used in:
Used in:
Artifact is the gArtLc (ListArtifacts/QueryArtifacts) row shape. Fields Fields 7-19 are a de-facto oneof keyed by type: exactly one of note, audio_overview, video_preview, report_config, mindmap_preview, slide_deck_preview, flashcard_config is populated per artifact, matching ArtifactType. These are each artifact-tree-local message shapes distinct from the top-level AudioOverview/VideoOverview/Report messages used by the Create*/Get* RPCs — the field numbers coincide but the wire shapes do not (AudioOverview.content/instructions are plain strings there; here they are structured payloads). See ArtifactAudioOverview etc. below.
Used as response type in: LabsTailwindOrchestrationService.CreateArtifact, LabsTailwindOrchestrationService.CreateAudioOverview, LabsTailwindOrchestrationService.CreateUniversalArtifact, LabsTailwindOrchestrationService.CreateVideoOverview, LabsTailwindOrchestrationService.GenerateArtifact, LabsTailwindOrchestrationService.GetArtifact, LabsTailwindOrchestrationService.RenameArtifact, LabsTailwindOrchestrationService.ReviseArtifact, LabsTailwindOrchestrationService.UpdateArtifact
Used as field type in: , , , ,
Field 6 is null in every observed capture; left unmodeled.
type NOTE
type AUDIO_OVERVIEW
type VIDEO_OVERVIEW
type REPORT
update_time is populated on every artifact regardless of type; it is always >= create_time (field 16).
Fields 12-14 are null in every observed capture; left unmodeled.
type 7 (mind map / infographic)
type 8 (slide deck)
Field 18 carries a wrapped list of timestamp rows, observed [[[1388, 553000000]]] on a failed NOTE artifact. The inner [secs, nanos] is a Timestamp; meaning (a processing duration or retry marker) is unconfirmed, so it is modeled generically.
inferred processing/retry times
type 9 (flashcards)
Inferred schema/version marker; constant 1 in every observed capture.
App's real wire position on gArtLc has never been observed (no type-5 artifact has appeared in any capture); field 10 was a guess that collided with the now-confirmed tailored_report position, so App is parked here pending a HAR that actually contains one.
update_cursor is a string encoding of update_time (field 11) as base64("{seconds}-{nanos}"), e.g. base64("1784614281-797501000"). Likely an opaque sort/pagination cursor; kept generic since its use is unconfirmed.
ArtifactAudioContent is the [topic, description, null, source_refs, language, prompt, length?, flag] generation-options blob at ArtifactAudioOverview field 2.
Used in:
e.g. "Blog Post"
Field 3 is null in every observed capture; left unmodeled.
ArtifactAudioOverview is the type-AUDIO_OVERVIEW gArtLc payload at Artifact field 8: [markdown_status, content, instructions]. This is a different shape than the top-level AudioOverview message (whose content and instructions are plain strings on Create/GetAudioOverview).
Used in:
rendered markdown, not a status code
same rich-text tree as chat rich_content
ArtifactDownloadVariant is one rendered-output link for an artifact preview: a URL plus an integer format code and (for audio) a MIME type. [url, format_code, mime_type?]
Used in: ,
ArtifactFileDetails is the five-string trailer returned by direct GetArtifact reads. The field meanings beyond filename and MIME type are unconfirmed; URLs are retained independently for lossless round-tripping.
Used in:
ArtifactFlashcardConfig is the type-9 (flashcards) gArtLc payload at Artifact field 19: [null, [null, language]].
Used in:
extracted_content is the source-derived rich-text document some flashcard decks carry (e.g. an extracted API reference table); null on the majority of captures.
Used in:
Field 1 is null in every observed capture; left unmodeled.
ArtifactImageRef is a [url, width, height] image reference.
Used in:
ArtifactMindMapConfig is the [null, language, null, int, int, int] config blob at ArtifactMindMapPreview field 1. orientation_code is inferred from the generated image dimensions; the remaining code meanings are unconfirmed.
Used in: ,
prompt is present for some custom mind maps and null for others.
Field 3 is null in every observed capture; left unmodeled. Observed 1 for landscape images and 2 for portrait images.
inferred visual-style selector
inferred template selector
ArtifactMindMapImageRef is a [url, width, height] image reference. Unlike ArtifactImageRef (the slide-deck variant), width/height are carried as integers here, not numeric strings.
Used in:
ArtifactMindMapPreview is the type-7 (mind map / infographic) gArtLc payload at Artifact field 15: [config, title, [slide]].
Used in:
ArtifactMindMapSlide is one [title, [url, width, height], description, text] entry in ArtifactMindMapPreview.slides.
Used in:
ArtifactNoteConfig is the [null, const, null, source_refs, language, flag, int] config blob inside ArtifactNotePreview.
Used in:
Present when the note was generated with a custom prompt.
constant 2 in every observed capture
Field 3 is null in every observed capture; left unmodeled.
inferred format selector
ArtifactNotePreview is the type-NOTE gArtLc payload at Artifact field 7: [null, config, thumbnail_url, thumbnail_url_2, has_audio?, download_variants, duration]
Used in:
Field 1 is null in every observed capture; left unmodeled.
duration is present-but-empty ([]) when there is no audio rendition yet, so it is wrapped in a message: a present TimestampPair marshals to [] when its own seconds/nanos are unset, instead of collapsing to null.
ArtifactReportConfig is the type-REPORT gArtLc payload at Artifact field 10: ["", [report_type, null, description_or_instructions, language, null, null, length_range_a?, length_range_b?, flag]]. The leading string is empty in every observed capture.
Used in:
Meaning unconfirmed; an explicit empty string in every observed capture.
Confirmed string carrying JSON. Inferred to be a mind-map node tree.
Used in:
Field 2 is null in every observed capture; left unmodeled.
custom prompt, or the report topic when no instructions were given
Fields 5, 6 are null in every observed capture; left unmodeled. length_range_a and length_range_b are never both populated in the same capture; which one is used appears to depend on report_type (a=1 pairs with report_type 1, b=2 with report_type 2), so both are kept as distinct optional positions rather than merged.
e.g. [2, 2]
e.g. [2, 2]
Used in:
Used in:
ArtifactSlideDeckConfig is the [null, language, format, length] config blob at ArtifactSlideDeckPreview field 1, mirroring the [format, length] pair EncodeCreateSlideDeckArgs sends on create (see internal/method/labs_tailwind_overview_custom.go SlideDeckFormat).
Used in:
Observed as a user-provided string; meaning unconfirmed.
Observed as 4; semantics are unconfirmed.
ArtifactSlideDeckPreview is the type-8 (slide deck) gArtLc payload at Artifact field 17: [config, title, [slide_image], download_url, download_url_2].
Used in:
ArtifactSlideEditInstruction is one [slide_index, text] revision-request pair.
Used in:
ArtifactSlideEditInstructions is the per-slide revision-request blob at ArtifactSlideDeckPreview position [5] (field 6): [[[slide_index, text], ...]]. Each entry pairs a zero-based slide index with the user's edit instruction for that slide (e.g. [0, "simplify this slide"]). Present only on slide-deck artifacts the user has requested edits on; absent otherwise. Surfaced by a gArtLc (QueryArtifacts) poll capture; the list is wrapped one level deep.
Used in:
ArtifactSlideImage is one [[url, width, height], description, text] entry in ArtifactSlideDeckPreview.slides.
Used in:
Used in:
Semantics unconfirmed. Observed as 8 on artifact sources.
Used in:
One suggestion pair. Pass description (optionally edited) as the instructions argument to CreateAudioOverview / CreateUniversalArtifact.
Used in:
Category tags for the suggestion, e.g. ["explanatory"]. Present only once suggestions have generated (absent on early poll snapshots).
Used in:
ArtifactTimestamps is the wrapped list carried at Artifact field 18: [[ [secs, nanos] ]] — an outer list of rows, each row an inline [seconds, nanos] pair (not a google.protobuf.Timestamp sub-message).
Used in:
Used in:
Video overview (confirmed from /tmp/notebooklm3.har)
6 unobserved.
mind map / infographic (see ArtifactMindMapPreview)
slide deck (see ArtifactSlideDeckPreview)
flashcards (see ArtifactFlashcardConfig)
Observed with a downloadable Markdown document; semantic name unconfirmed.
ArtifactUserState is the per-user, per-artifact state the orchestration service persists. Today the only observed payload is a single repeated PlaybackPosition recording the user's last playback position in an audio overview; the field is repeated to leave room for additional markers (resume points, chapter offsets) that the UI may emit later. Wire shape (HAR-verified 2026-04-25): [[[seconds, nanos]]] That is: ArtifactUserState is a message with field 1 = repeated PlaybackPosition, and a single PlaybackPosition encodes positionally as [seconds, nanos].
Used in: , ,
ArtifactVideoContent is the [source_refs, language, topic?, null, length, unknown_6?, null, flag?] generation-options blob at ArtifactVideoPreview field 3, the same family of shape as ArtifactAudioContent (a source-ref list plus language/topic/length/flag), but with source_refs and language/topic swapped in position relative to the audio variant. The array length varies (5, 6, or 8 observed) as trailing fields are omitted when unset, so every field past source_refs/language is optional.
Used in:
Field 4 is null in every observed capture; left unmodeled.
inferred format selector
Field 7 is null in every observed capture; left unmodeled. flag is carried as an int (1), not a JSON bool, unlike similarly named fields elsewhere.
ArtifactVideoPreview is the type-VIDEO_OVERVIEW gArtLc payload at Artifact field 9: [status?, thumbnail_url, content, video_url, download_variants, duration]. Unlike ArtifactAudioOverview, this was previously mismodeled as the unrelated Report message (field 9 used to be declared `Report tailored_report`), which is why the wire's positions 4-6 showed up as Report.unknown_4/5/6 in earlier verify runs.
Used in:
Field 1 is null in every observed capture; left unmodeled.
duration is [seconds, nanos].
AudioFormat captured kinds (HAR 2026-04-19+): 1 = "Deep Dive" — two-host conversation 2 = "Brief" — bite-sized overview 3 = "Critique" — expert review w/ feedback 4 = "Debate" — two-host opposing perspectives
Used in:
Used in:
Audio length options (confirmed from /tmp/notebooklm2.har analysis)
Used in:
Shorter audio overview
~10-15 minutes
~15-20 minutes (longer)
Used as response type in: LabsTailwindOrchestrationService.CreateAudioOverviewLegacy, LabsTailwindOrchestrationService.GetAudioOverview
Audio style types (confirmed from sqTeoe RPC in HAR analysis)
Used in: ,
"A lively conversation between two hosts, unpacking and connecting topics"
"A bite-sized overview to help you grasp the core ideas quickly"
"An expert review offering constructive feedback"
"A thoughtful debate illuminating different perspectives"
Encoding hints for batchexecute format
(message has no fields)
How to encode arrays
[[item1], [item2]]
[item1, item2]
[[[item1, item2]]]
How to handle empty/zero values
Used in:
BulkImportFromResearchResponse carries enriched Source descriptors in request order. The live API projects the generated response to its narrow BulkImportResult public type.
Used as response type in: LabsTailwindOrchestrationService.BulkImportFromResearch, LabsTailwindOrchestrationService.BulkImportFromResearchWire
BulkImportResult is the former partial projection of an imported Source. Deprecated: BulkImportFromResearchResponse now returns Source values.
Used in:
content holds inline markdown when this source is a note/text import (type=3). Leave empty for URL imports (type=2).
source_type matches the trailing enum int in the wire tuple: 2 = URL (url + title populated) 3 = NOTE (title + content populated)
Used in:
Used in:
Field 1 is null.
Fields 5 through 7 and 9 through 10 are null. Observed as a list containing a YouTube URL; semantics are unconfirmed.
BulkImportTextSourceLink is an observed [URL, title] source reference.
Used in:
Used in:
Fields 2 and 4 are null.
Used in: , , ,
Used in:
Used in:
Used in:
Used in: ,
Used in: ,
Used in:
Used in:
Fields 2 through 10 are null.
Used in:
Used in:
ChatMessage is one turn in a GetConversationHistory response. Field numbers are positional and match the observed wire layout (HAR-verified against a sanitized khqZz capture, 2026-07-20): [message_id, [secs,nanos], role, text, [content_segment...]] User turns (role = 1) populate text (field 4); assistant turns (role = 2) populate rich_content (field 5) instead. The live client reads this shape directly in api.parseConversationHistory; this message mirrors it so GetConversationHistoryResponse round-trips through the proto view.
Used in:
server-assigned message UUID
[seconds, nanos]
1 = user, 2 = assistant
plain text (user turns)
structured content (assistant turns)
Used in:
Used in:
Used in: , , ,
Field 2 is null.
Used in:
ChatStreamUnknown13 is an opaque repeated row carried by some streamed chat requests. Field meanings are unconfirmed.
Used in:
Used in:
Used in:
Used in: ,
ChunkRef is a [[chunk_id], ref_id] reference within a grounding record.
Used in:
CitationRef links a ContentSegment back to its source. The two id fields hold the same source UUID in every observed capture; ref is an integer whose meaning (chunk offset or citation index) is not yet confirmed.
Used in:
Collection is one collection row: a user-defined grouping of notebooks, returned in the collections scope of I3xc3c/agX4Bc. It occupies the same four slots as Label, but field 2 is a flat list of project ids rather than the wrapped ["uuid"] elements Label.sources uses. The split is exact across the corpus: 131 notebook-scope rows are wrapped and all 8 collections-scope rows are flat, with no row of either kind in the other scope.
Used in: ,
Member notebooks, as bare project id strings.
Same emoji slot as Label.emoji, set through the le8sX metadata mutation.
ContentAnnotation ties an offset range of the reply to the source indices that support it: [[null, start, end], [source_index...]].
Used in:
[0] [null, start, end]
[1] indices into grounding
ContentSegment is one span of an assistant turn's rich_content. Each segment carries its text and a citation reference; complex segments additionally carry a rich-text document payload not modeled here.
Used in:
Empty assistant segments carry an explicit empty string.
Field 2 ([1]) is an empty array in observed captures; left unmodeled.
[source_id, source_id, ref]
Field 4 ([3]) is an empty array in observed captures; left unmodeled.
rendered rich-text tree
Used in:
Context information, structure inferred from usage
Used in:
CreateLabelResponse returns the full refreshed list rather than just the new row, at a slot that depends on the request scope: field 2 in the notebook scope (8 observed) and field 3 in the collections scope (2 observed).
Used as response type in: LabsTailwindOrchestrationService.CreateLabel, LabsTailwindOrchestrationService.MutateLabelsMode
Field 1 (Label label) is null in every observed capture; the RPC returns the full refreshed label list at field 2 instead.
DeepResearchMainBlob is [report_tree, extra]. The extra string is present only on fast-research results.
Used in:
Used in:
Used in:
DeepResearchReportDetail covers the header's rendered report and the citation row's extracted text. Their wire layouts share the same six-slot positional group and differ only in which optional fields are populated.
Used in:
DeepResearchReportEntry covers both the report header at entry zero and the source-citation rows that follow it. Fast-research results use the same prefix, omitting the deep-only detail fields.
Used in:
HAR-verified wire shape (2026-07-21, e3bVqc/GetDeepResearchSessions), per session entry: [ conversation_id, // [0] UUID string [ // [1] inner project_id, // [0] UUID string [query, 1], // [1] query + int mode, // [2] 1 = fast, 5 = deep [ <report_tree> (, extra_str) ],// [3] main_blob; variable length state, // [4] int (6 observed) [research_id, plan_b64, 5, null, ts_str],// [5] DEEP ONLY (absent for fast) ], [secs, nanos], // [2] timestamp pair [secs, nanos], // [3] timestamp pair "157962509464", // [4] numeric timestamp string ] report_tree ([1][3][0]) is a 72-element deep-research report: element [0] is a [null, title, ...] header, elements [1..N] are source citations [url, title, ...9 fields]. ~334KB; distinct from the Span/chat document tree.
Used in: ,
Used in:
Used in:
DocTemplate is a prebuilt briefing-doc/study-guide template: [title, subtitle, system_prompt].
Used in:
Used in:
DocumentGuide is one per-source guide in a GenerateDocumentGuides (tr032e) reply. HAR-verified wire (more-requests3, keyed by source_id): [ [[source_id]], [summary], [[topic, topic, ...]], [] ] The live reader (api.Client.GenerateSourceGuide) hand-parses these positions directly; this message mirrors the wire for betool/beprotojson decode. Positions [1] and [2] wrap their payload one level deep, so each is modeled as a small wrapper message.
Used in:
[[source_id]]
[summary_text]
[[topic, topic, ...]]
[] in observed captures; meaning unconfirmed
DocumentGuideExtra is the empty list at DocumentGuide[3]. Modeled as a present-but-empty message so the [] round-trips rather than collapsing to null (mirrors ProjectCollaboratorTags).
Used in:
DocumentGuideId wraps the doubly-nested source id at DocumentGuide[0]: [[source_id]].
Used in:
DocumentGuideSummary wraps the summary text at DocumentGuide[1]: [summary].
Used in:
DocumentGuideTopics wraps the key-topic chips at DocumentGuide[2]: [[topic, topic, ...]].
Used in:
Used in:
Used in:
Used in:
Two sets of capability flags carried as JSON booleans.
Per-notebook limits/quotas (observed [null,500,600,500000,3]).
Used in:
Original image filename.
confirmed 1-based image position
inferred image-kind code; observed 2
Serving URL for the image (lh3.googleusercontent.com/notebooklm/…).
Used in:
field 1 reserved/unknown (observed null)
confirmed by the identical ProjectLimits slot
confirmed by the identical ProjectLimits slot
inferred byte/size limit; observed 500000
inferred tier code; observed 3
Used in:
Meaning unconfirmed; varies among featured presentations.
Used in:
Used in:
Used in:
Used in: ,
Wire shape: [content, null, role]
1 = user, 2 = assistant
Used in:
Observed default request options: [2, null, [1], [1]]
GetNotesEntry is one keyed GetNotes result: [note_id, note].
Used in:
Server timestamp of the notes snapshot.
GetNotesRichEntry is one keyed GetNotes result: [note_id, note].
Used in:
Meaning unconfirmed; observed as 2 on keyed entries in several captures.
GetNotesRichRecord is the response-side note tuple used by cFji9.
Used in:
GetNotesWireResponse is the keyed response shape returned by cFji9.
Used in:
Used in:
Fields 1 and 2 are null in observed requests.
GoogleDocsSourceInput is the AddSources field-1 Google Drive document variant. A 2026-07-23 capture verified this for application/vnd.google-apps.document.
Used in:
Used in:
Opaque resource/revision token for the doc (often empty).
inferred document size/count; unit unconfirmed
Used in:
Grounding is the detail of a GroundingRecord: [null, null, score, [reply_span], [source_spans], [chunk_ref], source_id].
Used in: , , , ,
Fields 1 and 2 ([0], [1]) are null in observed captures; left unmodeled.
[2] relevance score
[3] spans in the reply
[4] [[span...]] in the source
[5] [[chunk_id], ref_id]
[6] [source UUID]
GroundingRecord links reply spans to the source spans that ground them: [[source_id], [null, null, score, [reply_span], [source_spans], [ref], source_id]].
Used in:
[0] [source_id]
[1] the grounding detail
Used in:
Suggested prompt that expands the question.
Used in:
Used in:
Used in:
Used in:
Guide type for GenerateNotebookGuide (confirmed from /tmp/notebooklm3.har analysis)
Text outline
Mind map visualization
Guidebook-related messages
Used as response type in: LabsTailwindGuidebooksService.GetGuidebook
Used as field type in: , ,
Used in:
Used in:
Used in:
Used in: , , , , ,
Used in:
observed 2
Field 2 is null in every observed request.
Used in:
observed 1
Used in:
Used in:
stun: and turn: URIs
empty for STUN entries
empty for STUN entries
Label is one autolabel cluster, as returned in the notebook scope of I3xc3c/agX4Bc. The collections scope returns the same four slots but with a different element shape at field 2, so it is modeled separately as Collection.
Used in: , ,
e.g. "Generated Code", "Testing", "RPC and Networking"
Members of this cluster; each source id arrives wrapped as ["uuid"].
server-assigned UUID
CONFIRMED emoji, not a description. Field 4 is the emoji set by the le8sX metadata mutation: a capture sets "\U0001F4C1" on one label and a later read of the same label_id returns it here. Empty in 144 of 147 observed rows because most labels carry no emoji.
Used in:
LabelCreationRequest is CreateLabelRequest field 6. It is a single structure rather than a list of them: slot 1 holds the label or collection being created, and a collection create adds the notebooks to seed it with at slot 3. Observed as [[name, emoji]] for a label and [[name], null, [project_id]] for a collection.
Used in:
Field 2 is null in observed requests. Notebooks to seed a new collection with, as bare project id strings. Absent on notebook-scope label creates.
Used in:
Used in:
The metadata form sends [null, emoji] to set only the emoji, so name is optional rather than a bare string.
CONFIRMED emoji: a capture sets it here and the label subsequently reads back with that emoji at Label.emoji.
ListItem describes one list-item run within a span group: [null, null, nesting, {101:bullet, ...}]. Positions 1 and 2 are null in observed captures.
Used in: ,
Fields 1 and 2 ([0], [1]) are null in observed captures; left unmodeled.
[2] nesting depth (0,1,2)
[3] marker or shifted-marker metadata
[4] marker when field 4 is metadata
ListItemMarker is a shape union. Most list items carry their sparse marker object directly at position 4. A newer variant carries [null,null,flag] at position 4 and shifts the sparse marker object to position 5.
Used in:
Used in:
(message has no fields)
ListItemMarkerMeta is the [null, null, flag] tuple in shifted-marker items.
Used in:
ListMarker is the list-item style object, carried on the wire as a sparse object keyed by field number: {"101":"•", "102":1, "103":1, "104":0}. The bullet glyph cycles •/◦/▪ with nesting. marker_kind distinguishes unordered (1) from ordered (2) markers; the other counters' exact meanings remain unconfirmed.
Used in: ,
confirmed 1 for bullets, 2 for numbers
inferred per-list item number
inferred zero/one-based sequence counter
Used in:
Group semantics are unconfirmed because every observed list is empty.
[null, null, []]
[[]]
[null, []]
The three filter sub-messages each carry a single present-but-empty list. The list is wrapped in a StringList message so a present (non-nil) wrapper round-trips as [] rather than collapsing to null (an empty bare repeated field is indistinguishable from absent in proto3).
Used in:
fields 1-2 null; field 3 a present-but-empty string list.
Used in:
Present-but-empty in the full web request variant.
Used in:
Present-but-empty in the full web request variant.
field 1 null; field 2 a present-but-empty string list.
Used in:
LoadedSourceContentKind preserves the observed scalar discriminator and present-empty marker variants at LoadedSourceContent position 2.
Used in:
Used in:
(message has no fields)
Used in:
inferred image description
Used in: ,
Used in:
inferred layout discriminator
Used in:
Used in:
inferred formatting flag
inferred; meaning unconfirmed
inferred; meaning unconfirmed
Used in:
Used in:
Used in:
inferred; meaning unconfirmed
Used in:
Used in:
Used in:
Used in:
Used in:
inferred heading/list depth
Used in:
Fields 1 through 9 are null in observed requests.
Used in:
Used in:
Fields 1 and 2 are null in observed requests.
Used in:
Field 1 is null in observed requests.
Used in:
Used in:
Used in:
Used in:
Used in:
MutateAccountCapabilityPair is an observed two-integer capability pair.
Used in:
MutateAccountCapabilitySet is [null, null, null, [pair...]].
Used in:
MutateAccountChange carries a capability set at field 5.
Used in:
MutateAccountUpdate is [null, [change...]]. Pair semantics are unconfirmed.
Used in:
MutateAccountUpdateEnvelope wraps the update at field 1.
Used in:
Used in:
Metadata form uses field 1 (name) / field 2 (emoji); the source-attach form leaves field 1 null and carries the source ids at field 2, each id wrapped as ["uuid"] (SourceIdList, the same wrapper Label.sources uses).
CONFIRMED add: a capture attaches a project id here and a later read of the same collection shows that project as a member.
Same shape as add_projects at the next slot. A capture sends it against a collection that already contains the project, and no later read of that collection was captured, so the effect is UNOBSERVED. Removal is the obvious reading but is not confirmed, so the slot is left unnamed.
MutateLabelMutation is field 4: [[null, [[source_id]]]] (source-attach form) or [[name, emoji]] (metadata form). Field 1 wraps the inner mutation entry.
Used in:
Collection mutations carry a trailing list here that is empty in every observed capture, so its element type is unknown. Wrapped so the present-but-empty list marshals to [] rather than null, following the StringList idiom; the field is left unnamed because nothing has been seen inside it.
Used in:
Used in:
Used in:
Used as response type in: LabsTailwindOrchestrationService.MutateNote
Used as field type in:
A freshly created note (CreateNote/CYK0Xb) carries an explicit empty string here; plain proto3 drops it as the default value on re-encode, so that one degenerate CreateNote position is not round-trip-preserved (all content-bearing MutateNote replies are lossless).
NoteGroundingDetails wraps the unkeyed grounding-detail list at note field 4. For rich notes, each item is byte-for-byte equal to the Grounding part of the corresponding source-keyed GroundingRecord in RichDocument.grounding.
Used in: ,
NoteMetadata is the note-metadata blob carried at Note position [2] in CreateNote (CYK0Xb) and MutateNote (cYAfTb) replies: [1, "157962509464", [secs, nanos], null, null, [secs, nanos], false] field_1 is a constant 1; note_id_int is the server-side numeric note id (stable across a note's lifetime); the two timestamp pairs are the note's created and last-modified times (equal on the first write, the modified pair advancing on each subsequent MutateNote). Positions [3] and [4] are null in all observed captures; field_7 is a constant false. Modeled with optional scalars so the trailing false and the interior nulls round-trip.
Used in: , , ,
inferred schema version; observed 1
server numeric note id (wire: quoted string)
[secs, nanos]
positions [3], [4] are null in observed captures; left unmodeled.
[secs, nanos]
Meaning unconfirmed; constant false in observed captures.
NoteRecord is the response-side note tuple. Unlike Note, content_text has presence because CreateNote returns an explicit empty string.
Used in:
NoteRichText is a shape union. Older notes carry a plain string; rich notes carry the same positional RichDocument tree used by rendered chat content.
Used in: , ,
Used in:
NoteTimestamp is an inline [seconds, nanos] pair (two positional int fields, not a wrapped google.protobuf.Timestamp).
Used in:
Used in:
inferred update mode; observed 0
Field 5 is null in observed requests.
inferred state code; observed 0
Used in:
Used in:
Used in:
fields 3,4 reserved/unknown (observed null)
OffsetRange is a [null, start, end] character span of the rendered document.
Used in: , , ,
Position 1 is null in observed captures; left unmodeled.
Used in:
PlaybackPosition is a positional (seconds, nanos) tuple that mirrors google.protobuf.Duration's two int fields. Used inside ArtifactUserState to record the listener's place in an interactive audio overview.
Used in:
Used as response type in: LabsTailwindOrchestrationService.CreateProject, LabsTailwindOrchestrationService.GetProject, LabsTailwindOrchestrationService.MutateProject, LabsTailwindOrchestrationService.MutateProjectCover
Used as field type in: ,
Single per-notebook boolean flag (observed [false]); carried positionally.
meaning unconfirmed
Three per-notebook capability flags (observed [true,true,true]); exact meaning unconfirmed, so carried positionally.
Per-notebook limits/quotas, e.g. [6,500,500,500000,6] or, on a few notebooks, [null,500,600,500000,3] with the first slot elided — modeled as a message of optional fields so a null slot round-trips as null rather than breaking a repeated int64 (which cannot hold a null element).
Cover-image/presentation block for the notebook, e.g. [false, [[id, filename, 1, 2, image_url]], null, "Summary here", false]. Same positional shape as orchestration.proto's FeaturedProjectPresentation / FeaturedProjectImage (not reused directly to avoid a circular import: orchestration.proto already imports this file).
ProjectAnalyticsBuckets retains the observed one-field wrapper around the repeated metric buckets.
Used in:
ProjectAnalyticsPoint is one [timestamp, null, value] metric bucket.
Used in:
ProjectAnalyticsPointList retains the second observed wrapper around the repeated metric buckets.
Used in:
ProjectAnalyticsSeries contains the time buckets for one metric.
Used in:
ProjectCollaborator is one per-user wire entry: [email, role_int, [], [display_name, avatar_url]]. Field 3 is an empty list in observed captures; the display name and avatar live in a nested profile at position 4. role_int 1 = OWNER.
Used in:
[] in observed captures
[display_name, avatar_url]
ProjectCollaboratorTags is the empty list at collaborator entry position 3. Modeled as a present-but-empty message so the [] round-trips (rather than collapsing to null).
Used in:
ProjectCoverImage: [id, filename, position, image_kind, image_url]. Field 1 holds a UUID (not a URL) in this context, unlike orchestration.proto's FeaturedProjectImage.url — otherwise the same shape.
Used in:
Original image filename.
confirmed 1-based image position
inferred image-kind code; observed 2
Serving URL for the image (lh3.googleusercontent.com/notebooklm/…).
Used in:
Fields 1 through 7 are null in observed requests.
ProjectCoverMutationUnknown4 is the [null, title] metadata tuple observed on a project cover mutation. Its semantics are unconfirmed.
Used in:
ProjectCoverPresentation is Project field 15: a cover-image/presentation block, positionally identical to orchestration.proto's FeaturedProjectPresentation.
Used in:
Meaning unconfirmed; varies among featured presentations.
Used in:
Semantics unconfirmed. Observed as [8], [7], and [2] in cover mutations, and as [] in the legacy preset-only variant.
Used in:
ProjectDetailsFlags is the visibility flags tuple at ProjectDetails[1]: [flag_0, flag_1], both true when the notebook is fully public. Present as null when private.
Used in:
ProjectDetailsPermissions is the [3, true, true] blob at ProjectDetails[6].
Used in:
ProjectLimits is Project field 11: a 5-slot quota tuple. Modeled as optional fields (not repeated int64) because the first slot is null on some notebooks.
Used in:
observed 6, or null
observed 500
observed 500/600
observed 500000
observed 6/3
Used in: ,
or similar
Meaning inferred; true in every observed owned and featured project.
field 4 reserved/unknown field 5 reserved/unknown
or similar
Inferred from false on owned projects and true on public featured ones.
Meaning unconfirmed; true in every observed project.
inferred access code; observed 1
Inferred from false on owned projects and true on public featured ones.
Meaning unconfirmed; varies independently among featured projects.
inferred sharing code; observed 1/3
[null, [null, 1]]: small nested message, meaning unconfirmed.
inferred; present on owned projects
Meaning unconfirmed; varies among featured projects.
ProjectMetadataExtra is ProjectMetadata field 20: [null, [null, 1]]. Field 1 is null in all observed captures; field 2 is itself a 2-field message whose own field 1 is null and field 2 an observed int (1).
Used in:
field 1 ([0]) is null in all observed captures; left unmodeled.
[1]
Used in:
Observed true in ListRecentlyViewedProjects captures (null in GetProject).
[1] inferred; observed 1/2
ProjectUserProfile is the [display_name, avatar_url] pair carried at collaborator entry position 4.
Used in:
PromoCard is one upsell-card placement.
Used in:
[0] e.g. 2230 (matches slot campaign)
[1] rendering payload
field 3 ([2]) null in all captures; left unmodeled. placement_id is inferred from its reuse in the event context.
[3] e.g. 2351
[4] confirmed duplicate of placement_id
[5] confirmed duplicate of id
[6] e.g. "NOTEBOOKLM_TIER_ULTRA_LIGHT_CONSUMER_USER"
fields 8, 9 ([7], [8]) null in all captures; left unmodeled. Meaning unconfirmed; false in every observed card.
[9]
field 11 ([10]) is a present-but-empty list in all captures; wrapped so the empty repeated marshals to [] not null.
PromoCardAction is the "Manage subscription" call-to-action.
Used in:
[0]
fields 2, 3 ([1], [2]) null in all captures; left unmodeled.
[3] e.g. "Manage subscription"
field 5 ([4]) null in all captures; left unmodeled.
[5] dup of label
fields 7, 8 ([6], [7]) null in all captures; left unmodeled.
[8] click tracking
PromoCardContent pairs the card's icon with its click action.
Used in:
[0]
[1]
PromoCardEvent wraps a logged UI event: [context, kinds, token, sig].
Used in: ,
[0]
[1] e.g. [2] (click) or [14] (impression)
[2] opaque base64 tracking token
[3] opaque base64 signature
PromoCardEventContext carries the placement coordinates repeated in both the click and impression events.
Used in:
[0] confirmed match to PromoCard.id
[1] inferred placement coordinate
field 3 ([2]) null in all captures; left unmodeled. Meaning unconfirmed; observed as 43 in both event kinds.
[3]
Confirmed discriminator: 1 on click, absent on impression.
[4]
field 6 ([5]) null in all captures; left unmodeled.
[6]
field 8 ([7]) null in all captures; left unmodeled. [8] present on click ([[ref]], wrapped one extra layer like SpanList/SourceIssueList), absent (null) on impression.
field 10 ([9]) null in all captures; left unmodeled.
[10] confirmed match to PromoSlot.campaign_id
[11] confirmed duplicate of placement_id
field 13 ([12]) null in all captures; left unmodeled.
[13] large signed decimal string
PromoCardIcon: [null, icon_name, glyph_id].
Used in:
field 1 ([0]) null in all captures; left unmodeled.
[1] e.g. "NotebookLM icon"
[2] e.g. "edit"
PromoCardLink: [null, null, url].
Used in:
fields 1, 2 ([0], [1]) null in all captures; left unmodeled.
[2]
PromoCardLinkWrapper: [[null, null, url], enabled_flag].
Used in:
observed false
PromoCardRef: [id, campaign_id, tags].
Used in:
[0] e.g. 2230
[1] e.g. 627
[2] e.g. [9]
PromoCardRefList wraps PromoCard.refs: present-but-empty in all captures, so it needs the wrapper idiom (see SpanList) to round-trip [] instead of collapsing to null.
Used in: ,
PromoCardRender is the 21-position rendering blob for a PromoCard. Only positions 10 and 21 carry data in observed captures.
Used in:
fields 1-9 ([0]-[8]) null in all captures; left unmodeled.
[9] icon + action
fields 11-20 ([10]-[19]) null in all captures; left unmodeled.
[20] impression tracking
PromoLogEntry is one acknowledged log event: [slot, cards, status].
Used in:
[0] slot/campaign descriptor, e.g. [null, "1", 627].
[1] repeated upsell cards (one observed per response).
[2] observed 0 in all captures; needs presence to avoid collapsing to null on empty re-encode.
PromoSlot identifies a promo placement: [_, surface_locale, campaign_id]. Reused both as the top-level slot and nested inside PromoCardEventContext.
Used in: ,
field 1 ([0]) is null in all observed captures; left unmodeled.
[1] e.g. "1"
[2] e.g. 627
Used in:
Used in:
field 3 is null in observed responses
RequestArtifactTypeFilter is RequestContext field 5: [[1,4,8,10,2,3,6,9]].
Used in: ,
RequestClientCaps is RequestContext field 4: [1, null×9, [1]] (11 elements).
Used in: , , , , ,
inferred capability-envelope version; observed 1
Fields 2-10 ([1]-[9]) are null in every observed request; left unmodeled.
observed [1]; code meaning unconfirmed
RequestContext is the client-capabilities preamble the web UI prepends to most orchestration requests. Observed as [2, null, null, [1, null×8, [1]]] — with an extra artifact-type filter list at field 5 in ListArtifacts.
Used in: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,
Observed constant 2 (protocol/surface version).
Field 2 ([1]) is null in every observed request.
ListArtifacts prepends the requested artifact-type filter here, e.g. [[1, 4, 8, 10, 2, 3, 6, 9]]; absent (null) on other requests.
RequestSurface is the optional [1] marker carried by some UI reads.
Used in: , , , ,
Used in:
Used in:
wire shape unverified; capture HAR before encoding
Used in:
Revision identifier (UUID).
RichContent is an assistant turn's structured payload: [segment, [grounding...], [], [annotation...]]. The segment carries the text and rich-text document; the grounding and annotation lists tie the reply back to its sources.
Used in:
[0] text + rich document
[1] reply-to-source grounding
Field 3 ([2]) is an empty array in observed captures; left unmodeled.
[3] source annotation index
RichDocument is the rendered rich-text form of an assistant turn: a tree of character-offset spans plus per-source grounding records. It is the [body, [], [], grounding, flag] payload at ContentSegment field 5.
Used in: , , , , ,
Fields 2 and 3 are empty arrays in observed captures; left unmodeled.
small int (1); meaning TBD
Used in:
Used in:
Separator marks a zero-content boundary span. It is empty on the wire ([]) but present, distinguishing a separator span from an ordinary one.
Used in:
(message has no fields)
Additional message not in sharing.proto
Used in: , ,
Used as response type in: LabsTailwindOrchestrationService.MutateSource, LabsTailwindOrchestrationService.RefreshSource
Used as field type in: , , , , ,
Observed as bare integers. Their semantics are unconfirmed.
Content-download URL (usercontent.google.com/download?c=…).
Drive viewer/upload URL for the source blob.
Blob reference describing the stored source content.
SourceAnnotation maps an offset range of the rendered document back to a source: [[source_id], [null, start, end]].
Used in:
[0] [source_id]
[1] [null, start, end]
Used in:
Blobref path, e.g. "/contrib_service/blobrefs/notebooklm/nos_files/…".
field 2 reserved/unknown (observed null)
Opaque upload tokens carried with the blob.
Used in:
Drive/document identifier for the file.
Size in pages or units (observed 59 for a PDF).
Inferred Drive resource key; observed as an explicit empty string.
Used in: ,
SourceIdList wraps a single source UUID in its own array ([source_id]).
Used in: , , , , , , , , , , , , , , , , , , , , , ,
Used in:
Google Docs import: [drive_id, mime_type, 1, drive_id].
Field 3 is null in observed text-import requests.
observed 3
Fields 5-10 are null in observed text-import requests.
inferred import mode; observed 1
Used in:
Used in:
Used in:
SourceLanguageDetection is SourceMetadata field 17: [[[lang, confidence], ...]] — field 1 wraps the ranked guess list.
Used in:
Used in:
BCP-47 code, e.g. "en", "lb"
0..1
Used in:
Present zero is distinct from an omitted source type on the wire.
Source origin URL(s), e.g. the web page or Gutenberg URL a source was imported from.
inferred source length/count; unit unconfirmed
Underlying file descriptor for uploaded/imported sources.
Human-readable source title/heading.
Detected source languages with confidence scores, e.g. [[["en", 0.988], ["lb", 0.012]]] — an outer list carrying one ranked list of [lang, confidence] guesses.
Source MIME type, e.g. "application/pdf".
Used in:
Used in:
Reason/issue detail for a source in an error or disabled state (observed [null,null,[]] — only the repeated issue list at field 3 is populated, empty when the source is healthy).
Observed as 0 and 3; meaning unconfirmed.
Used in: ,
Used in:
field 1 reserved/unknown Size/quota triple observed [null, 650690, 500000] on some sources.
Issue list for the source, always present (empty [] when the source is healthy).
Present-but-empty in most captures; individual code meanings unconfirmed.
Present-but-empty in a source settings variant; meanings unconfirmed.
Observed [1]; individual code meanings unconfirmed.
SourceSettingsIntList wraps a repeated int64 so a present-but-empty list round-trips as [] rather than null.
Used in:
SourceSettingsSize is SourceSettingsDetail field 2: [null, 650690, 500000], a byte/char size pair (field 1 null in observed captures).
Used in:
inferred current size; observed 650690
inferred limit; observed 500000
Used in:
Used in:
Used in: ,
Span is one character-offset range [start, end] of the rendered document and its content. Spans nest recursively: a block span's content is a group of child spans, a leaf span's content is text. content is a shape union (see SpanContent).
Used in: , , ,
Offsets are explicitly present so a legitimate 0 (the document start) round-trips as 0 rather than an absent null.
Inline images carry [image_url, null, image_id] at position 4 instead of text content. The URL is an authenticated NotebookLM media URL; image_id is the stable UUID for the embedded image.
table carries a [type_code, columns, rows] table block instead of the usual content/hidden_content shapes; fields 1-4 and 6-11 are null when it is present.
Code blocks carry a [code_text, language] pair at position 7 instead of the usual content (fields 3..6 and 8..11 are null). start/end still bound the block within the document.
Hidden/thinking blocks carry their content at position 9 instead of 3 (fields 4..8 are null). The content is the same recursive span shape.
Separator spans (e.g. the empty [432,433] between blocks) carry an empty marker array at position 12 instead of content; fields 4..11 are null. Modeled as a present-but-empty message so the trailing [] round-trips.
SpanCodeBlock is a fenced code block within a rich-text document: [code_text, language]. Carried at Span position 7. Observed languages include "protobuf" and "go".
Used in: ,
SpanContent is a shape union: a span holds EITHER a text leaf (["text"] or ["text", marks]) OR a group of nested child spans ([[spans], ...]), at the same wire position. beprotojson selects the case by shape.
Used in:
["text", marks?]
[[spans], meta?, null?, items?]
SpanElement is a shape union used by SpanGroup.spans. Most entries are the normal [start, end, content] Span shape, but some captures contain a bare integer leaf (for example 0 or 11) at the same repeated position.
Used in:
SpanGroup is a container span's content: a list of child spans plus optional layout metadata.
Used in:
[0] child spans or scalar leaves
[1] e.g. [null, indent]
Field 3 ([2]) is null in observed captures; left unmodeled.
[3] list-item style
SpanGroupMeta is the [null, indent, flag?] metadata trailing a span group.
Used in:
Position 1 is null in observed captures; left unmodeled.
flag is seen true on at least one non-offline-resource notice span; meaning not yet confirmed.
SpanImage is an inline image reference: [image_url, null, image_id].
Used in:
Position 2 is null in observed captures; left unmodeled.
SpanLayers holds the document body as two parallel layers over the same text: the block tree (headings, paragraphs, list items) and a per-source annotation index mapping offset ranges back to their source.
Used in:
SpanList wraps a list of spans in one extra array layer ([[span...]]), the shape grounding uses for its source spans.
Used in:
SpanTable is a table block within a rich-text document: [type_code, columns, rows]. Observed type codes vary; their meaning is not yet known. columns is the column count; each row contains nested cell Spans.
Used in:
SpanTableRow is one table row: [start, end, cells]. Its content is a bare list of cell Spans, unlike an ordinary Span's content (which goes through the SpanContent leaf/group shape union), so it is not itself a Span.
Used in:
SpanTableRowMeta is the [null, flag] trailer on table rows.
Used in:
Used as response type in: LabsTailwindOrchestrationService.StartDeepResearch, LabsTailwindOrchestrationService.StartDeepResearchWire
Used in:
Field 1 carries the human-readable status string when present.
StringList wraps a repeated string so a present-but-empty list marshals as [] instead of null. Mirrors the SourceIssueList idiom.
Used in: , , , ,
SubmitFeedbackContent carries the question and full answer context.
Used in:
SubmitFeedbackSignal preserves the observed selector shape. The values' meanings are unconfirmed because only one direction is captured.
Used in:
SubmitFeedbackTurn identifies the conversation turn that supplied feedback.
Used in:
semantics unconfirmed
Used in:
Used in:
Used in:
TextLeaf is the innermost span content: a run of text with optional positional formatting marks.
Used in:
[null x7, bold?] positional flags
Used in: ,
TextMarkColorOrFlag is a shape union. Position 6 is a boolean formatting flag in older spans and an [red, green, blue] tuple in styled rich text.
Used in: ,
Used in: ,
TextMarkFontOrFlag is a shape union. Position 5 is a boolean formatting flag in older spans and a [font_family, weight] tuple in styled rich text.
Used in: ,
TextMarks carries the positional formatting marks on a text leaf. Observed forms include [true] (flag1, on inline headings/labels), [null x7, true] (flag8, on code/identifier runs), and [null, null, null, url] (link, a hyperlink target). Boolean marks are carried as JSON booleans on the wire, not batchexecute's 1/0; exact bold/italic/code meanings are not yet confirmed, so they are modeled generically. KNOWN ASYMMETRY, deliberately not modeled: responses carry these flags as JSON booleans but CYK0Xb requests carry the identical structure with 1/0 instead ([0,0,0,null,null,null,null,0,0] against [false,false,false,null,null,null,null,false,false]). The split is by direction and absolute across the corpus — 1960 numeric occurrences on requests, 1931 boolean on responses, no crossover — with no discriminator field to key on. json_bool is a static per-field choice, so no single setting round-trips both, and the same asymmetry affects ListItem and SpanTableRowMeta. Preserving it would mean either a form-remembering codec or a duplicate request-side span tree, both of which touch the shared path that carries ~687k spans, for a field no client of this package sends. Two CYK0Xb request records therefore stay lossy on purpose.
Used in:
[3] hyperlink target URL
observed true on code/identifier runs
inferred style code; observed 2
TimestampPair wraps a [seconds, nanos] pair so it can be present-but-empty ([]) on the wire, distinct from being absent (null).
Used in:
Used in:
Fields 1 and 2 are null in observed requests.
Fields 5 and 6 are null in observed requests.
Field 8 is null in observed requests.
Fields 11 through 14 and 16 are null in observed requests.
Observed as custom mind-map configuration. Repetition semantics are unconfirmed.
UniversalArtifactOptionsUnknown10 is the observed [null, [kind, null, optional_text]] trailer. Its semantics are unconfirmed.
Used in:
Used in:
Used in:
Used in:
Used in:
Present when an audio request carries a custom prompt.
Field 3 is null in observed requests.
Field 6 is null in observed requests.
Used in:
Field 1 is null in observed requests.
Used in:
Semantics unconfirmed. Observed as a plan-mode instruction string.
Used in:
Field 4 is null in observed requests.
semantics unconfirmed
Used in:
Fields 1 and 2 are null in observed requests.
UpdateProjectUserStateKeys is field 4: [["notebook_lm_state...."]]. Field 1 is the repeated list of dotted state-key paths being updated (e.g. "notebook_lm_state.saved_source_panel_view").
Used in:
Used in:
Pinned-state responses carry true here; saved-panel responses carry null.
UpdateProjectUserStateValue is field 3: [null, [null, 2]].
Used in:
field 1 ([0]) is null in the observed capture; left unmodeled.
Used in:
Pinned-state requests carry numeric 1 here; saved-panel requests carry null.
confirmed state value; observed 2
Used in:
Video style (1=autoselect, 2=classic, 3=whiteboard)
Video style options (confirmed from /tmp/notebooklm3.har analysis)
Used in:
Let system choose the best style
Classic presentation style
Whiteboard-style presentation
Used in:
Channel or uploader name.