Skip to content

feat(google_sheets): new Google Sheets tool plugin with OAuth and Each user signs in (1.0.0) - #4182

Merged
crazywoola merged 2 commits into
langgenius:mainfrom
ForeignKeyCN:feat/google-sheets-tool
Nov 2, 2026
Merged

crazywoola merged 2 commits into
langgenius:mainfrom
ForeignKeyCN:feat/google-sheets-tool

Conversation

@ForeignKeyCN

Copy link
Copy Markdown
Contributor

Summary

A new Google Sheets tool plugin (tools/google_sheets). It reads and writes spreadsheets from workflows and agents. Rows are handled as records keyed by the header row (the way agents and workflows think); cells can also be read and written as raw A1 ranges. It is built like the other Google plugins: Calendar (#4173), Gmail (#4180) and Drive (#4181).

Auth

  • OAuth from the Dify console: one Google account for the workspace.
  • Each user signs in: every chat user signs in with their own Google account.
    • Uses authorization code + PKCE through a plugin endpoint (GET /google_sheets/callback) that only stores the one-time code.
    • Per-user tokens are Fernet-encrypted in plugin storage, keyed by a hash of client_id | Dify user ID, and never appear in tool output.
    • After sign-in, the agent reports which account was used.
    • An unticked permission, invalid_grant or a 401 leads to a new sign-in.
    • The callback page warns about forwarded links.
    • google_sheets_sign_out forgets the sign-in.
  • Scopes:
    • spreadsheets: read and write.
    • drive.metadata.readonly: only to find spreadsheets by name. File contents are not read.

Tools (prefixed google_sheets_: the new Agent rejects duplicate tool names across plugins)

Area Tool
Spreadsheets google_sheets_find_spreadsheets (by name, newest first, across shared drives), google_sheets_get_spreadsheet (title, link, sheets with sizes), google_sheets_create_spreadsheet (sheet names and a header row)
Rows google_sheets_read_rows: objects keyed by the header row, with row_number; optional column = value filter; blank rows skipped
google_sheets_append_rows: maps keys to the header order; an empty sheet gets the keys as its header
google_sheets_update_rows: matches on key_column and changes only the given columns. update_all_matches updates every match. Never appends; unmatched keys are reported
google_sheets_upsert_rows: updates matches and appends the rest
google_sheets_delete_rows: by row number or column = value, deleted bottom-up
Ranges google_sheets_read_range (formatted, raw or formulas), google_sheets_write_range (a JSON grid), google_sheets_clear_range (formatting kept)
Sheets google_sheets_add_sheet, google_sheets_rename_sheet, google_sheets_delete_sheet
  • Spreadsheets can be given by ID or URL. Column names are case-insensitive.
  • Keys that aren't columns are an error unless add_missing_columns adds them to the header row.
  • Values are written with USER_ENTERED, so numbers, dates and =formulas behave as in the UI.
  • Sheet names are quoted for A1 notation ('Q2 ''final'''), and spreadsheet IDs and ranges are encoded as path segments.
  • Every tool returns typed output variables (success / error plus its fields).

Release Notes

  • New plugin: Google Sheets tools.
    • Find, inspect and create spreadsheets.
    • Read, append, update, upsert and delete rows by column name.
    • Read, write and clear cell ranges.
    • Add, rename and delete sheets.
  • Two ways to authorize: OAuth (one shared account), and Each user signs in for chat agents, where each person works on their own spreadsheets.

Change Type

  • Documentation / non-plugin change
  • Non-LLM plugin (tools, extensions, datasource, etc.)
  • LLM plugin

Screenshots / Videos

The README includes a chat in which the agent, as the signed-in user:

  • creates a spreadsheet;
  • updates one row and appends a missing one;
  • reads the rows back.

Testing

  • Unit tests: 38 passed (pytest tests). They cover:
    • The sign-in flow.
    • A1 helpers (column letters, sheet-name quoting).
    • Rows:
      • reading: skips blank rows, case-insensitive filter, URL as spreadsheet ID, unknown sheet or column;
      • appending: header order, unknown columns rejected or added;
      • updating: by key, first match vs all matches, unmatched reported;
      • upserting;
      • deleting bottom-up, with the header row protected.
    • Range writes with encoding, render options and an invalid grid.
    • Creating and finding spreadsheets (query escaping).
    • Every tool's output variables, the manifest and provider.
  • Self-hosted Dify (Community), Each user signs in, real Google account, in an agent chat:
    • sign-in;
    • created a spreadsheet with a header and two rows;
    • changed one row and added a missing one (upsert);
    • read all rows back.
  • Not run against Google: row deletion, range read/write/clear, sheet add/rename/delete and finding spreadsheets (unit tests only).

Checklist

  • I have read the contribution guidelines
  • New plugin, version 1.0.0

The agent retypes the sign-in link in its reply, and a long random state
does not always survive that: in a real chat one character changed case,
so the callback endpoint could not recognize the sign-in.

The tool now returns <sign-in endpoint>?start=<12 lowercase characters
without look-alikes>, and the endpoint redirects to the sign-in page it
stored. The state and PKCE values go to the provider and back without
passing through the agent.
@crazywoola
crazywoola deployed to tools/google_sheets November 2, 2026 16:18 — with GitHub Actions Active
@crazywoola
crazywoola merged commit cc119dd into langgenius:main Nov 2, 2026
4 checks passed

This branch was successfully deployed

1 active deployment
tools/google_sheets — fadb3211 Deployed Nov 2, 2026 by crazywoola via test (tools/google_sheets) #2960
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.

2 participants