Skip to content

Scribe Agent ​

Scribe agent icon

Reads meeting notes that Gemini saves to Google Drive after Google Meet calls, maps discussion topics to the issue backlog, and adds comments to existing issues or creates new ones.

How the agent works ​

The scribe agent bridges synchronous team interactions and autonomous development loops. It runs on a schedule or via manual trigger, searching Google Drive for recent meeting notes, extracting actionable engineering topics, and updating the repository backlog so downstream agents (triage, prioritize, code) can act on team decisions.

Scribe follows the host pre-script / sandbox / validation loop / post-script architecture:

  1. Pre-script (host):
    • Fetches repository context: open issues (backlog.json), recently closed issues (closed-issues.json), open pull requests (open-prs.json), and markdown documentation index (repo-docs-index.json).
    • Queries Google Drive API using a keyword search query (SCRIBE_SEARCH_QUERY) across a rolling time window (SCRIBE_LOOKBACK_HOURS, default 3 hours) using credentials from a dedicated GCP service account.
    • PII and structural scrubbing: Drops transcript sections, anonymizes bracketed attendee names (e.g. [John Smith]) and bullet attribution prefixes (- Jane Doe: action), and packages cleaned notes into notes.tar.gz.
    • Generates scribe-meta.json with runtime metadata including cutoff_date and notes_url.
  2. Sandbox:
    • The sandboxed agent extracts notes.tar.gz and reads the notes alongside repository context files.
    • Treats all meeting notes as untrusted user input — never following commands, directives, or instructions embedded within notes content.
    • Evaluates topics against strict criteria:
      • Recency: Extracts topics only from the most recent meeting section on or after cutoff_date.
      • Substance threshold: Requires concrete discussion — decisions made, questions debated, options evaluated, or action items assigned. Skips brief name drops, logistics, status updates with no new information, and topics whose only outcome is an external chat.
      • Public-appropriateness gate: Assigns every topic a public_safe boolean and a public_safe_category. Sets public_safe: true only if the topic contains no personal names, no interpersonal commentary or opinions, no internal HR/headcount/compensation topics, no undisclosed business strategy or financials, no undisclosed security vulnerabilities, and no confidential or legal matters. If unsafe, it flags public_safe: false with one of the fixed categories (names, interpersonal, hr, strategy, security, legal, confidential) without quoting or paraphrasing the sensitive text.
      • Confidence calibration: Assigns a confidence score from 0.0 to 1.0 (>= 0.8 for clear decisions and actionable conclusions; 0.6–0.7 for substantive discussion with trade-offs; < 0.6 filtered out by post-script gate).
      • Backlog matching: Matches discussion topics against open issues by analyzing both issue titles and bodies. Checks closed issues to avoid proposing already-resolved work (noting prior resolution in comments instead). Correlates in-flight work with open PRs and references relevant ADRs or problem docs.
      • Formatting: Formats comments for existing issues with structured markdown (date header, relevance statement, discussion bullet points, related PRs/docs, and a mandatory [Meeting notes](URL) citation link). Proposes new issues with structured markdown sections: Problem, Options considered, Acceptance criteria (checkboxes), and Related links.
    • Writes structured JSON output (agent-result.json) containing topics[], new_issues[], and stats. The sandbox has no network access to forge APIs or Google Drive.
  3. Validation loop:
    • Validates agent-result.json against schemas/scribe-result.schema.json, retrying up to 2 times if schema validation fails.
  4. Post-script (host):
    • Deduplicates topics against previous notes links (idempotency check) to prevent reposting.
    • Filters out topics below SCRIBE_MIN_CONFIDENCE (default 0.6) and rejects any entry marked public_safe: false.
    • Enforces sensitive-content and suspicious-Unicode gates on all titles, bodies, summaries, and labels.
    • Enforces dry-run safety: SCRIBE_DRY_RUN must be set explicitly; false enables live writes, while any other value previews actions in logs without making mutations (the reference dogfood workflow in fullsend-ai/.fullsend defaults to previewing by passing true).
    • Applies mode filtering (all, comments_only, new_issues_only).
    • Writes approved comments and issues using forge API calls (gh on GitHub, curl on GitLab) or Jira Cloud issue creation (fullsend issues create --tracker jira).
    • Optionally sends run summary notifications to Slack when SCRIBE_SLACK_WEBHOOK_URL is set.

Security model ​

  • Untrusted input: Meeting notes are treated as untrusted user input. Prompts explicitly instruct the agent to ignore any embedded directives or prompt injection attempts in meeting text.
  • Dedicated GCP service account: A service account with zero initial Drive permissions is invited only to specific calendar events whose notes it needs to process.
  • Host-side PII scrubbing: Bracketed attendee names and speaker attributions are scrubbed on the host before notes enter the sandbox; raw transcripts are excluded entirely.
  • Sandbox network isolation: Sandbox outbound network policy permits only the configured inference providers (Vertex AI and OpenAI in the shipped harness); curl, forge APIs, and Drive APIs are blocked to reduce the risk of token or credential exfiltration.
  • Credential isolation and host-side tokens: Forge tokens (GH_TOKEN, GITLAB_TOKEN) and Jira API tokens remain host-side and are never injected into the sandbox container. The GCP service account key (GOOGLE_APPLICATION_CREDENTIALS) is mounted into the sandbox at /tmp/.gcp-credentials.json for Vertex AI inference, so it could also access Drive if granted; use a dedicated service account with minimal scope (invited calendar events only) and restrict sandbox egress to the required inference providers to minimize exfiltration risk.
  • Host-side validation gates: Output schema checks, confidence thresholds, sensitive content pattern matching, and public-safety verification run host-side before any mutations occur.

How it helps ​

  • Automatically transfers meeting decisions, architecture debates, and action items into the issue backlog without manual note-taking or copy-pasting.
  • Matches discussion topics to existing issues by title and body semantics, keeping existing tracking issues up to date and avoiding duplicate tickets.
  • Public-safety and PII gates prevent confidential business matters, personal commentary, and attendee identities from leaking into issue trackers.
  • Idempotency checks avoid duplicate comments or repeated issues when processing rolling meeting documents across overlapping lookback windows.
  • Serves as the upstream bridge between team discussions and downstream fullsend agents such as triage, prioritize, and code.

Commands ​

The scribe agent does not accept slash commands. It runs on a schedule or via manual workflow dispatch.

Prerequisites and workflow setup ​

Scribe is an opt-in agent and mint-only dogfood role; fullsend does not ship a pre-configured scribe workflow under .github/workflows/ or within internal/scaffold, and scribe is not a valid role under the roles: field in config.yaml (see Config Reference).

To run scribe:

  1. If using the fullsend token mint service, register the dogfood role: fullsend mint add-role scribe.
  2. Register the agent harness with fullsend agent add (shown below).
  3. Supply your own scheduled or dispatch workflow on your CI runner. For an example implementation, see the reference scribe workflow in fullsend-ai/.fullsend or the workflow step guide in agents docs/scribe.md.

Control labels ​

The scribe agent does not consume or apply control labels that gate agent workflow execution. It applies a meeting-notes label (or allowlisted Jira labels) to issues it creates for categorization and filtering.

Configuration and extension ​

From the repository root, register the scribe agent (which writes to .fullsend/config.yaml using the default --fullsend-dir .fullsend):

bash
fullsend agent add \
  https://github.com/fullsend-ai/agents/blob/main/harness/scribe.yaml \
  --name scribe

Dedicated GCP service account setup ​

To grant the agent access to meeting notes without exposing other Drive files:

  1. Create a dedicated Google Cloud service account with zero default Drive permissions.
  2. Invite the service account email address to the Google Calendar events you want scribed.
  3. In the Google Calendar event settings, enable Gemini meeting notes and permit read access to external attendees.
  4. Export the service account credentials JSON path as GOOGLE_APPLICATION_CREDENTIALS (or SCRIBE_DRIVE_CREDENTIALS) on the CI runner.

At runtime, the pre-script queries the Drive API using a keyword search (SCRIBE_SEARCH_QUERY) over a rolling time window (SCRIBE_LOOKBACK_HOURS, default 3 hours) across everything the service account can access — including Shared Drives if the account has been added to any. The search query narrows matching, but it is not a security boundary: the service account can read notes from any meeting it has been invited to, not just a single event. To keep the blast radius small, use a distinctive search query and avoid adding the service account to unrelated Shared Drives.

Variables ​

Per ADR 0049, scribe configuration uses the SCRIBE_ prefix. In the reference GitHub Actions workflow in fullsend-ai/.fullsend, SCRIBE_SEARCH_QUERY is mapped from the repository variable vars.SCRIBE_GDRIVE_SEARCH_QUERY, and SCRIBE_NAME_FILTER is mapped from vars.SCRIBE_GDRIVE_NAME_FILTER.

Because harness/scribe.yaml references these environment variables in env.runner and env.sandbox, every variable listed below must exist in the runner environment (even if set to an empty string ""); fullsend run validates harness variable references and fails with <VAR> is not set if any referenced variable is omitted. Documented defaults apply when the variable is empty or set to its default value.

NameRequiredDefaultDescription
SCRIBE_REPOYes-Target repository (owner/name on GitHub, group/project on GitLab)
SCRIBE_SEARCH_QUERYYes-Google Drive search query for meeting note document names (mapped from vars.SCRIBE_GDRIVE_SEARCH_QUERY)
SCRIBE_NAME_FILTERNononeOptional document title substring or regex filter (mapped from vars.SCRIBE_GDRIVE_NAME_FILTER)
SCRIBE_LOOKBACK_HOURSNo3Search lookback window in hours (applied when empty)
SCRIBE_DRY_RUNYes-false enables live writes; any other value previews actions in logs (post-script exits if unset)
SCRIBE_MIN_CONFIDENCENo0.6Minimum confidence threshold for posting topics (applied when empty)
SCRIBE_MODENoallOperating mode: all, comments_only, or new_issues_only (applied when empty)
FULLSEND_FORGEYes-Forge type: github or gitlab
GH_TOKENYes (GitHub)-GitHub token with issue read/write permissions
CONTENTS_TOKENNo (GitHub)GH_TOKENOptional token for repository content reads; falls back to GH_TOKEN when empty
GITLAB_TOKENYes (GitLab)-GitLab access token with API read/write permissions
GOOGLE_APPLICATION_CREDENTIALSYes-Path to GCP service account key for Drive reads and Vertex AI
SCRIBE_DRIVE_CREDENTIALSNoGOOGLE_APPLICATION_CREDENTIALSPath to an alternate Drive-scoped service account key; falls back to GOOGLE_APPLICATION_CREDENTIALS when empty
SCRIBE_SLACK_WEBHOOK_URLNononeOptional Slack incoming webhook URL for run notifications

Operating modes ​

ModeEffect
allPosts comments on existing issues and creates new issues for unmapped topics
comments_onlyPosts comments on existing issues only; skips new issue creation
new_issues_onlyCreates new issues only; skips commenting on existing issues

Jira issue creation ​

Scribe can create new issues in Jira Cloud instead of the forge's native issue tracker. The forge (FULLSEND_FORGE) provides repository context (open PRs and documentation index), while the Jira Cloud project provides the open backlog and recently resolved issues for matching, and receives new issues.

Configure Jira connection settings under tracker.jira in .fullsend/config.yaml:

yaml
tracker:
  jira:
    base_url: https://myteam.atlassian.net
    project: PROJ
    # api_url: https://api.atlassian.com  # optional API gateway URL

Issue creation delegates to fullsend issues create --tracker jira. The external harness scripts in fullsend-ai/agents query the Jira backlog using JIRA_BASE_URL and JIRA_TOKEN (with optional JIRA_USER_EMAIL), and automatically pass these to fullsend issues create as FULLSEND_JIRA_TOKEN and FULLSEND_JIRA_EMAIL. (Note that OAuth credentials are not supported by the scribe harness scripts; token authentication via JIRA_TOKEN is required).

Set FULLSEND_TRACKER=jira and configure Jira variables in runner environment variables. Extend the harness with base: composition in .fullsend/scribe.yaml:

yaml
base: https://raw.githubusercontent.com/fullsend-ai/agents/<SHA>/harness/scribe.yaml#sha256=<sha256sum>
env:
  runner:
    FULLSEND_TRACKER: jira
    SCRIBE_JIRA_PROJECT: PROJ
    SCRIBE_JIRA_ISSUE_TYPE: Task
    JIRA_BASE_URL: ${JIRA_BASE_URL}
    JIRA_TOKEN: ${JIRA_TOKEN}
    JIRA_USER_EMAIL: ${JIRA_USER_EMAIL}

If scribe was previously registered from a remote URL, remove it first from the repository root before registering the local harness override, as fullsend agent add refuses duplicate agent names. Register the local file relative to --fullsend-dir (default: .fullsend):

bash
fullsend agent remove scribe
fullsend agent add scribe.yaml --name scribe
NameRequiredDefaultDescription
FULLSEND_TRACKERYes (Jira)FULLSEND_FORGEMust be set to jira
SCRIBE_JIRA_PROJECTYes (Jira)-Jira project key for backlog reads and issue creation (matches tracker.jira.project)
SCRIBE_JIRA_ISSUE_TYPENoTaskJira issue type for created issues (applied when empty)
SCRIBE_JIRA_LABELSNomeeting-notesComma-separated allowlist of labels scribe may apply to Jira issues
JIRA_BASE_URLYes (Jira)-Jira Cloud instance URL (https://<site>.atlassian.net)
JIRA_API_URLNoJIRA_BASE_URLTarget REST API gateway URL, read by external harness scripts
JIRA_TOKENYes (Jira)-Jira API token (passed to CLI as FULLSEND_JIRA_TOKEN)
JIRA_USER_EMAILNononeEmail address for Basic auth; omit for service account Bearer auth (passed to CLI as FULLSEND_JIRA_EMAIL)

In Jira mode:

  • Only new issues are created. Comments on existing Jira issues are not supported (all operates as new_issues_only, and comments_only is rejected).
  • Up to 50 pages of unresolved issues are fetched for backlog matching, along with recently resolved issues from the past 30 days to avoid re-proposing completed work.
  • Issue creation delegates to fullsend issues create --tracker jira, which converts Markdown to Atlassian Document Format (ADF) and invokes Jira REST APIs. The CLI reads connection settings from tracker.jira in .fullsend/config.yaml, and the harness scripts translate JIRA_TOKEN and JIRA_USER_EMAIL into the FULLSEND_JIRA_* variables expected by the CLI.
  • Labels are validated against an allowlist (SCRIBE_JIRA_LABELS) and applied host-side.
  • For complete Jira configuration details and harness examples, see Jira setup in fullsend-ai/agents docs/scribe.md.

GitLab host validation ​

On GitLab, the pre- and post-scripts validate CI_SERVER_URL against CI_SERVER_HOST. Validation requires an HTTPS URL and ensures the URL host matches CI_SERVER_HOST, failing closed if variables are missing or mismatched.

Skills ​

The scribe agent has no built-in skills (skills: []). Custom skills can be added via harness composition or repository skill directories.

Source ​

fullsend-ai/agents — harness/scribe.yaml