feat(skills): salvage airtable skill + wire skill API keys into .env (#15838)#16291
Merged
Conversation
Convert the airtable skill from 'skills.config.airtable.api_key' (config.yaml, wrong bucket for a secret) to 'prerequisites.env_vars: [AIRTABLE_API_KEY]' (~/.hermes/.env), matching every other bundled skill that authenticates with an API token. Why the original shape was wrong: - metadata.hermes.config is for non-secret skill settings (paths, preferences) per references/skill-config-interface.md. Storing a bearer token under skills.config.* also triggered the documented 'hermes config migrate' nag-on-every-run problem. - The Quick Reference's 'AIRTABLE_API_KEY=...' bash line couldn't read skills.config.airtable.api_key anyway — it's a yaml path, not an env var. Follow-up polish on the same pass: - Added version/author/license frontmatter to match notion/linear. - Added prerequisites.commands: [curl]. - Setup section now specifies the PAT format (pat...) that replaced legacy 'key...' API keys in Feb 2024, plus the three required scopes (data.records:read/write, schema.bases:read) and the per-base Access list requirement. - Clarified PATCH vs PUT and pagination (100 records/page cap). - Swapped verification from 'hermes -q ...' (non-deterministic) to a curl /v0/meta/bases call that returns a verifiable HTTP status code.
Adds NOTION_API_KEY, LINEAR_API_KEY, TENOR_API_KEY, and AIRTABLE_API_KEY to OPTIONAL_ENV_VARS so: - They persist to ~/.hermes/.env via save_env_value like every other key Hermes knows about, instead of being ad-hoc variables the user has to hand-edit the dotfile for. - load_env() / reload_env() populate os.environ from .env on every startup — the user sets the key once, skills keep working across restarts without losing access. - hermes setup / hermes config show surface them as known optional vars with the correct signup URL (linear.app/settings/api, airtable.com/create/tokens, etc.). These four entries use category="skill" (new) rather than "tool". tools/environments/local.py auto-adds every category=tool/messaging entry to _HERMES_PROVIDER_ENV_BLOCKLIST, which stops env passthrough from leaking provider credentials into the execute_code sandbox (GHSA-rhgp-j443-p4rf). Skill API keys are the opposite case — the point is for the agent's subprocess to see them so curl can read Authorization headers — so they must be outside the blocklist. The new category is inert for that check. All four entries are advanced=True: they show up in 'hermes config' and 'hermes status' displays, but do not nag users who have never touched those skills during setup checklists. E2E verified: save_env_value → reload_env → os.environ populated → skill_view reports setup_needed=False → env_passthrough registers the key for subprocess inheritance.
- scripts/release.py: map sonoyuncudmr@gmail.com -> Sonoyunchu so the check-attribution CI job and release notes credit Soynchu correctly. - website/docs/reference/skills-catalog.md: add the airtable row to the productivity bundled-skills table.
Expand the airtable skill from bare CRUD to a full Hermes-shaped cookbook matching the linear/notion neighbors, and trim the description to fit the 60-char system-prompt cutoff. Hermes-specific additions: - Explicit 'use the terminal tool with curl — not web_extract or browser_navigate' guidance, matching the same note in linear. - Note that AIRTABLE_API_KEY flows from ~/.hermes/.env into the subprocess automatically via env_passthrough, so curl calls don't need to re-export it. - Prefer 'python3 -m json.tool' (always present) over jq (optional) for pretty-printing, with -s on every curl to keep output clean. - Read-before-write workflow that resolves record IDs via filterByFormula instead of guessing. Cookbook expansion (new vs original): - Field-type reference table (text, select, multi-select, attachment, linked record, user) with the exact write-shape Airtable expects. - typecast flag for auto-coercing values / auto-creating select options. - performUpsert PATCH for idempotent sync by merge field. - Batch create/delete endpoints (10-record cap per call). - Sort + fields query params with URL-encoding (%5B / %5D). - Named-view query that applies saved filter/sort server-side. - Full pagination loop template (while loop with offset). - Common filterByFormula patterns (exact match, contains, AND/OR, date comparison, NOT empty). - Rate-limit backoff guidance (Retry-After header, per-base budget). - Airtable error-code reference (AUTHENTICATION_REQUIRED, INVALID_PERMISSIONS, MODEL_ID_NOT_FOUND, INVALID_MULTIPLE_CHOICE_OPTIONS) so the agent can map failures to user-actionable fixes instead of just retrying. Also: description trimmed from 183 chars (truncated to 60 in system prompt, losing 'filter/upsert/delete' trigger terms) down to 59 chars that render whole: 'Airtable REST API via curl. Records CRUD, filters, upserts.' Catalog row updated to match. SKILL.md grew from 115 to 228 lines — still under the 500-line soft cap and below the linear skill (297 lines) which serves the same role for GraphQL.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #15838. Salvages @Sonoyunchu's bundled Airtable skill onto current main and layers on the follow-up work needed to make skill credentials stop falling out of
.env.What this PR makes true
Bundled skills that use API keys (
airtable,linear,notion,gif-search) now have their credentials registered in Hermes'OPTIONAL_ENV_VARScatalog. The user sets the key once — viahermes setup,hermes config set, or by hand in~/.hermes/.env— and every subsequent session can see it. Previously these keys were only mentioned in each SKILL.md's setup section and left as the user's problem to remember, with no persistence hook.Commits
feat(skills): add bundled Airtable productivity skill— @Sonoyunchu's original (cherry-picked, authorship preserved).fix(skills/airtable): use .env credential pattern matching notion/linear— SKILL.md rewrite. Original usedmetadata.hermes.config.airtable.api_key(wrong bucket for a secret perreferences/skill-config-interface.md— that interface is for non-secret skill settings; secrets belong in.env). Also added version/author/license frontmatter,prerequisites.commands: [curl], PAT-specific setup (legacykey...keys were deprecated Feb 2024), the three required token scopes, pagination cap, PATCH vs PUT clarification, and a deterministic/v0/meta/baseshealth check for verification.feat(config): register bundled-skill API keys in OPTIONAL_ENV_VARS— addsNOTION_API_KEY,LINEAR_API_KEY,TENOR_API_KEY,AIRTABLE_API_KEY. Uses a newcategory: "skill"so the sandbox env blocklist intools/environments/local.pydoes NOT auto-block them — skills legitimately needcurlto readAuthorization: Bearer $KEYfrom the subprocess environment, which is the opposite of provider/tool credentials (GHSA-rhgp-j443-p4rf). All four entries areadvanced=Trueso they don't nag users who have never touched those skills.chore: docs + attribution— AUTHOR_MAP entry forsonoyuncudmr@gmail.com, skills-catalog.md row.Validation
skills.config(wrong)prerequisites.env_vars: [AIRTABLE_API_KEY]AIRTABLE_API_KEYin OPTIONAL_ENV_VARScategory=skill,advanced=TrueLINEAR_API_KEY,NOTION_API_KEY,TENOR_API_KEYsave_env_value, auto-loaded viareload_env_HERMES_PROVIDER_ENV_BLOCKLISTcontains skill keys_HERMES_PROVIDER_ENV_BLOCKLISTcontains provider/tool keysenv_passthrough.is_env_passthrough(AIRTABLE_API_KEY)after skill_viewTests: 171 passed across
tests/hermes_cli/test_config.py,tests/tools/test_skills_tool.py,tests/tools/test_skill_env_passthrough.py,tests/tools/test_env_passthrough.py,tests/tools/test_local_env_blocklist.py,tests/hermes_cli/test_env_sanitize_on_load.py.E2E verified the full round-trip for all four skills:
save_env_value→reload_env→os.environpopulated →skill_viewreportssetup_needed=False→env_passthroughregisters the key for subprocess inheritance.Credit to @Sonoyunchu for the original Airtable skill.