Io Connectors
Kilo-Org/kilo-marketplace
Guides development and usage of I/O connectors in Apache Beam.
How to build and run GCP Pub/Sub stream subscribers in Python under pystreams/ — the multi command (start at pystreams/src/pystreams/cmd/multi.py), the graminfra.pubsub publisher/subscriber library…
$ npx skills add speakeasy-api/gram --skill gram-pubsub-python -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install speakeasy-api/gram gram-pubsub-python --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/speakeasy-api/gram.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/gram-pubsub-python .claude/skills/gram-pubsub-python && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "gram-pubsub-python" agent skill from https://github.com/speakeasy-api/gram/tree/main/.agents/skills/gram-pubsub-python into .claude/skills/gram-pubsub-python/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "gram-pubsub-python", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/speakeasy-api/gram/tree/main/.agents/skills/gram-pubsub-pythonType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add speakeasy-api/gram --skill gram-pubsub-python -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install speakeasy-api/gram gram-pubsub-python --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/speakeasy-api/gram.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.agents/skills/gram-pubsub-python .agents/skills/gram-pubsub-python && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "gram-pubsub-python" agent skill from https://github.com/speakeasy-api/gram/tree/main/.agents/skills/gram-pubsub-python into .agents/skills/gram-pubsub-python/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "gram-pubsub-python", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add speakeasy-api/gram --skill gram-pubsub-python -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install speakeasy-api/gram gram-pubsub-python --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/speakeasy-api/gram.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.agents/skills/gram-pubsub-python .cursor/skills/gram-pubsub-python && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "gram-pubsub-python" agent skill from https://github.com/speakeasy-api/gram/tree/main/.agents/skills/gram-pubsub-python into .cursor/skills/gram-pubsub-python/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "gram-pubsub-python", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/speakeasy-api/gram.git --path .agents/skills/gram-pubsub-python--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add speakeasy-api/gram --skill gram-pubsub-python -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install speakeasy-api/gram gram-pubsub-python --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/speakeasy-api/gram.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.agents/skills/gram-pubsub-python .gemini/skills/gram-pubsub-python && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "gram-pubsub-python" agent skill from https://github.com/speakeasy-api/gram/tree/main/.agents/skills/gram-pubsub-python into .gemini/skills/gram-pubsub-python/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "gram-pubsub-python", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install speakeasy-api/gram gram-pubsub-pythonInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add speakeasy-api/gram --skill gram-pubsub-python -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/speakeasy-api/gram.git skills-src && mkdir -p .github/skills && cp -r skills-src/.agents/skills/gram-pubsub-python .github/skills/gram-pubsub-python && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "gram-pubsub-python" agent skill from https://github.com/speakeasy-api/gram/tree/main/.agents/skills/gram-pubsub-python into .github/skills/gram-pubsub-python/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "gram-pubsub-python", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add speakeasy-api/gram --skill gram-pubsub-python -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install speakeasy-api/gram gram-pubsub-python --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/speakeasy-api/gram.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.agents/skills/gram-pubsub-python .opencode/skills/gram-pubsub-python && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "gram-pubsub-python" agent skill from https://github.com/speakeasy-api/gram/tree/main/.agents/skills/gram-pubsub-python into .opencode/skills/gram-pubsub-python/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "gram-pubsub-python", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
gram-pubsub-pythonHow to build and run GCP Pub/Sub stream subscribers in Python under pystreams/ — the multi command (start at pystreams/src/pystreams/cmd/multi.py), the graminfra.pubsub publisher/subscriber library…
Gram Pubsub Python is an agent skill from speakeasy-api/gram. How to build and run GCP Pub/Sub stream subscribers in Python under pystreams/ — the multi command (start at pystreams/src/pystreams/cmd/multi.py), the graminfra.pubsub publisher/subscriber library, and the anyio runtime mirroring the Go gram streams process. Activate for ANY Python Pub/Sub work in Gram: adding or changing a pystreams subscriber/handler, NLP/ML scanning consumers (Presidio PII detection, prompt-injection classifiers, spaCy/transformer models over streams), registering a receiver, the local…
Its SKILL.md is about 4.1k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Backend & APIs, covering Event-driven systems. It works with Python and Google Cloud. The repository describes itself as: Securely scale AI usage across your organization. A single stack to Connect, Secure, Observe and Distribute agents, MCPs, and Skills within your company. The licence is AGPL-3.0.
2 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 4d32da1. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
miseuvFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md. Its commands use uv, which can reach the network depending on how they are called.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Gram Pubsub Python loads about 4.1k tokens when it runs. Until then it costs about 247 tokens; SKILL.md has 1,897 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from speakeasy-api/gram at commit 4d32da1, republished under its AGPL-3.0 licence (© speakeasy-api). 1,897 words, ~4,135 tokens.
.claude/skills/gram-pubsub-python/SKILL.md (or your agent's skills folder).pystreams)pystreams is the Python home for Pub/Sub stream consumers in the Gram
monorepo. It runs alongside — not instead of — the Go gram streams process,
and it consumes the same proto-declared Pub/Sub topology. This skill covers
the Python runtime: how a subscriber is written, registered, and run. For
declaring the topic/subscription itself (the (gcp.pubsub.v1.topic) /
(gcp.pubsub.v1.subscription) proto options and infra/gen/kcc.yaml), use the
gram-pubsub skill — that half is language-agnostic and shared.
The original and default stream-processing home is the Go streams component
(server/cmd/gram/streams.go). Go's concurrency model and the GCP Pub/Sub Go
SDK's use of it are substantially better suited to high-throughput message
fan-out than the Python equivalent, async Python included. So the rule of thumb
is: build new consumers in Go streams by default.
pystreams exists for the cases where Python's ecosystem is the deciding
factor — overwhelmingly working with language models, transformers, NLP/ML
use cases. Presidio (PII detection), prompt-injection classifier models, spaCy,
and the transformer tooling these depend on are Python-first and have no
comparable Go story. Reaching into that ecosystem from Go would mean
reimplementing or shelling out; running the consumer in Python is the honest
path. So the decision is not "which language do I prefer" but "does this
consumer need a Python-only library to do its job?" If yes, pystreams; if no,
Go streams.
The first real pystreams consumer is the Presidio PII scanner
(pystreams/src/pystreams/risk/handler.py); ping is a heartbeat used to keep
the publish→subscribe path exercised, mirroring the Go ping.
infra/proto/**.proto topic/subscription declarations (shared, see gram-pubsub)
└─ buf generate ─┬─ infra/gen/** Go types + infra/gen/kcc.yaml
└─ infra/gen_py/** Python types (gram.*.v1.*_pb2)
infra/gram_infra/pubsub/ the Python publisher/subscriber library
├─ broker.py PubSubBroker / EmulatedPubSubBroker (mirrors infra/pkg/gcp)
├─ publisher.py Publisher[M], pubsub_publisher_for_message
├─ subscriber.py Subscriber[M], pubsub_subscriber_for_message
└─ discover.py proto-option → resource-name resolution
pystreams/ the runnable service ("multi" command)
└─ src/pystreams/cmd/multi.py the entrypoint — START HEREinfra/gram_infra (the gram-infra package) is a uv workspace member shared by
pystreams; it holds both the generated Python protobufs and the hand-written
Pub/Sub convenience layer. pystreams is the deployable that wires handlers
onto subscriptions and runs the receive loops. Read the library as the Python
counterpart of infra/pkg/gcp/ — the docstrings deliberately point back to the
Go files they mirror, so the two layers stay behaviorally aligned.
multi.py firstpystreams/src/pystreams/cmd/multi.py is the whole service in one screen. It is
a Click command (multi) that anyio.runs an async multi(...) coroutine.
Walking it top to bottom teaches the runtime:
--gcp-project-id, or a throwaway when an
emulator host is set (the emulator doesn't care about the project)._build_broker): EmulatedPubSubBroker when
--pubsub-emulator-host is set (it reconciles topics/subscriptions on
demand, since the emulator has no Config Connector), else PubSubBroker
(assumes Config Connector already provisioned everything). This is the exact
prod-vs-local split the Go layer makes.with broker:) — it owns the
publisher/subscriber clients and flushes + closes them on exit, including a
clean Ctrl-C teardown.ReceiverGroup.receivers.receive(...) call per subscription.health_state.set_ready()) only after receivers are
wired, so /readyz doesn't go green before the service can actually consume.The structured-concurrency shape matters: everything runs as a child task of
that single task group, so any fatal error or a shutdown signal tears the whole
process down together for a clean restart — the Python analogue of the Go
errgroup in streams.go.
Exactly like the Go side: write a handler, then register it.
A handler is an async callable (message, meta) -> None. The proto message type
is the topic's payload; meta is gram_infra.pubsub.subscriber.MessageMetadata
(id, attributes, delivery_attempt). The return/raise is the ack/nack
signal, identical to Go: returning normally acks; raising nacks
(triggering redelivery and eventual dead-lettering if the subscription declares
a dead_letter policy). You never call ack()/nack() yourself in the
callback form — the library does it from your handler's outcome.
The minimal shape is PingHandler (pystreams/src/pystreams/ping/handler.py):
a class holding its dependencies, with an async def handle(self, message, meta).
Register handle (the bound method), not the class.
The real reference is PresidioHandler (pystreams/src/pystreams/risk/handler.py).
It demonstrates the patterns that matter for ML/NLP consumers:
AnalyzerEngine loads a spaCy model — expensive. Do it in __init__, not per
delivery.asyncer.asyncify(...) so it runs in a worker thread and the loop stays
responsive. The loop-lag monitor exists precisely to make this kind of stall
visible before it becomes an outage.Protocol. PresidioHandler
depends on a narrow Analyzer protocol, so tests inject a lightweight fake
instead of loading the NLP model (see pystreams/tests/test_risk_handler.py).PresidioScanner subscription declares no dead_letter policy, so a raised
exception would nack and redeliver the same message for the full retention
window — one poison input could loop for 30 days. Because this is best-effort
shadow processing, the handler swallows Exception and returns (acking)
rather than poisoning the subscription, logging the error type only. Catch
Exception, never BaseException, so cancellation (graceful shutdown) still
propagates. Match the policy to intent: raise only when you genuinely want the
message retried.type(exc).__name__ and not the exception message.multi.pyAdd a receivers.receive(...) call in the marked block, mirroring the topic and
subscription proto declarations:
receivers.receive(
presidio_request_pb2.PresidioRequest, # the TOPIC message type → fixes the handler's `message` type
presidio_scanner_pb2.PresidioScanner, # the SUBSCRIPTION marker message (carries the subscription option)
PresidioHandler(logger).handle, # your async handler callback
)The three arguments line up one-to-one with the proto options the gram-pubsub
skill describes: the topic-declaring message, the subscription-declaring marker,
and the handler. ReceiverGroup.receive (pystreams/src/pystreams/cmd/receiver.py)
resolves a Subscriber via pubsub_subscriber_for_message, wraps your handler
in per-message tracing (deps/tracing.py — a stream.handleMessage span tagged
with the topic/subscription proto names, continuing the publisher's trace via
W3C context), and starts the receive loop as a child task. It's the direct
analogue of mustReceive/receiverGroup in streams.go, so each subscription
is one line at the call site.
Go and Python can consume the same topic through separate subscriptions:
gram.ping.v2.Messagehas both aProcessormarker (consumed by Go) and aPyProcessormarker (consumed bypystreams). If you want a Python consumer of a topic the Go side already reads, declare a new subscription marker rather than stealing the existing one. Declaration is agram-pubsubtask.
Subscriber.receive (infra/gram_infra/pubsub/subscriber.py) handles the
hard parts so handlers stay tiny: it unmarshals the payload into a fresh proto
instance (a malformed payload is nacked and never reaches you), runs handlers
concurrently up to a bounded max_concurrency, isolates a raised handler error
to that one message (logged with context, then nacked), bridges the
google-cloud-pubsub library's background threads onto the event loop without
parking a worker thread per subscriber, and tears down cleanly on
cancellation — nacking anything buffered-but-undispatched so the broker
redelivers immediately instead of waiting out the ack deadline. There is also a
Subscriber.stream() async-iterator form for explicit per-message ack/nack, but
receive (the callback form) is what pystreams uses; prefer it.
Most events are published by the Go server where they originate. When Python
does need to publish, use pubsub_publisher_for_message(broker, MessageType) →
await publisher.publish(msg) (infra/gram_infra/pubsub/publisher.py). It
proto-marshals the body and tags it with content-type: application/x-protobuf
and schema: <proto full name> — the same two attributes the Go publisher
sets — so messages are interoperable across languages, and it injects W3C trace
context so a Python→Python or Go→Python hop continues the trace. publish is a
coroutine; await it.
pystreams runs locally against the shared Pub/Sub emulator — no Config
Connector, no real GCP.
pitchfork start pystreams-multi or the pitchfork mcp server if
available (runs uv run multi in the pystreams/ dir).mise.toml sets PUBSUB_EMULATOR_HOST (and the
pubsub-emulator compose service the Go side uses is the same one). With that
env var set, multi builds an EmulatedPubSubBroker, which lazily creates the
topic and subscription on first use — so you don't provision anything locally.GRAM_PYSTREAMS_CONTROL_HOST/PORT (default
127.0.0.1:8089), serving GET /healthz (liveness, always 200) and
GET /readyz (503 until receivers are wired, then 200; flips back to 503 the
instant shutdown begins so a rolling deploy drains in-flight handlers).GRAM_SERVICE_VERSION, GRAM_ENVIRONMENT,
GRAM_LOG_LEVEL, GRAM_LOG_PRETTY) and GCP config (GRAM_GCP_PROJECT_ID,
PUBSUB_EMULATOR_HOST) all have CLI flags too; see cmd/flags_*.py.mise run test:pystreams (pytest, asyncio_mode = "auto" so async
tests need no decorator). Tests exercise handlers with fakes/protocols and the
structlog capture helper — no live broker or model load. Follow that:
inject a fake analyzer/dependency and assert on captured logs and ack/nack
behavior. (Per repo convention, the broker/subscriber library tests also run
under anyio's trio backend, not just asyncio, to keep them backend-agnostic.)mise run lint:pystreams runs ty check and
pyrefly check. Both are strict; keep handlers fully typed.hk fix formats changed files (Python included) across the branch.mise run gen:infra runs buf generate, which emits both Go (infra/gen/)
and Python (infra/gen_py/, via the protocolbuffers/python + pyi plugins).
Import the Python types as from gram.<pkg>.v1 import <name>_pb2 and the library
as from gram_infra.pubsub import .... After any change to a .proto under
infra/proto/, regenerate and commit per the gram-pubsub skill — the Python
side picks up the new _pb2 modules from the same run. The protobuf runtime
floor is pinned to match buf's generator version (see infra/pyproject.toml);
keep them in lockstep if the buf plugin version changes.
Tracing, logging, and the loop-lag metric are wired through OpenTelemetry's API
and structlog. The per-message span and W3C propagation mirror the Go receiver
exactly (deps/tracing.py). Note that until a TracerProvider/MeterProvider
is installed in the process, the OTel instruments resolve to the API's implicit
no-ops — recording stays cheap and correct, and the data flows out once a
provider is configured, with no change to handler code. So don't be surprised if
spans/metrics aren't exported yet; the wiring is provider-agnostic by design.
streams. Only add a consumer here when it genuinely needs a
Python-only library (NLP/ML). Most other use cases belong in streams.go.asyncify / anyio.to_thread.run_sync. A blocking handler stalls all
subscriptions on the same loop. The loop-lag histogram is your early warning.__init__, not per
message.Exception, log, return) so one bad
message can't poison the subscription for the whole retention window. Always
let cancellation (BaseException) propagate.gram-pubsub task. Adding a topic or subscription means
editing a .proto and running mise run gen:infra — not editing pystreams.
Use a new subscription marker (e.g. a Py* variant) for a Python consumer of
an already-consumed topic.pystreams/ —
pystreams is a uv workspace member that depends on gram-infra, and the
single uv.lock lives at the root (see the header of Dockerfile.pystreams).© speakeasy-api, AGPL-3.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in .agents/skills/gram-pubsub-python of speakeasy-api/gram.
Open the folder on GitHubat commit 4d32da1
Gram Pubsub Python next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Gram Pubsub Python this skillspeakeasy-api/gram | 272 | — | ~4.1k | Automated safety check: Pass | AGPL-3.0 | |
| Io ConnectorsKilo-Org/kilo-marketplace | 189 | — | ~1.3k | Automated safety check: Pass | Apache-2.0 | |
| AWS Serverless Edazxkane/aws-skills | 367 | 4 repos | ~3.2k | Automated safety check: Pass | MIT | |
| Windmill Trigger Type Checklistwindmill-labs/windmill | 18k | — | ~4.7k | Automated safety check: Pass | Custom licence | |
| Opensource Guide Coachcalf-ai/calfkit-sdk | 149 | 1 repos | ~2.1k | Automated safety check: Pass | Apache-2.0 | |
| Azure Event Hubs Python SDK Guidemicrosoft/skills | 3.1k | 1 repos | ~2.3k | Automated safety check: Pass | MIT |
Kilo-Org/kilo-marketplace
Guides development and usage of I/O connectors in Apache Beam.
zxkane/aws-skills
AWS serverless and event-driven architecture expert based on Well-Architected Framework.
windmill-labs/windmill
Checklist of every backend, frontend, CLI and capture change needed to add a new TriggerCrud-based trigger type, such as Azure, GCP or Kafka, to Windmill.
calf-ai/calfkit-sdk
A skill your agent uses when a user wants guidance on starting, contributing to, growing, governing, funding, securing, or sustaining an open source project, or asks about contributor onboarding…
microsoft/skills
Covers producer, consumer, and checkpoint-store setup for Azure Event Hubs streaming in Python, with Entra ID auth and partition targeting.
DavidVujic/python-polylith
Create a Polylith base with poly create base — the entry point of a deployable application (HTTP API, CLI, message-queue consumer, AWS Lambda handler, GCP Cloud Function, scheduled job).
speakeasy-api/gram
A skill your agent uses when automating the Gram dashboard in a browser, capturing screenshots, inspecting pages.
speakeasy-api/gram
A skill your agent uses when adding, changing, restyling, reviewing, validating, or previewing a Gram/Speakeasy transactional email, in Go or in LMX/MJML — a template<name.go, a TemplateKey…
speakeasy-api/gram
A skill your agent uses when adding, changing, or styling UI in client/admin (the Gram admin dashboard) that touches shadcn/ui — a button, dialog, table, sidebar, badge, select, tabs, tooltip, card…
speakeasy-api/gram
A skill your agent uses when adding, editing, reviewing, testing, or locating a reviewed skill distributed with the Platform MCP plugin; triggers include "Platform MCP skill", "platformmcpskills"…
speakeasy-api/gram
A skill your agent uses when changing or reviewing Gram ClickHouse schemas, migrations, queries, inserts, access principals, bootstrap SQL, Cloud compatibility, partial migration failures, or…
speakeasy-api/gram
A skill your agent uses when gating a feature behind a flag, dogfooding or gradually rolling out a change, choosing between productfeatures and PostHog feature flags, adding or checking a product…
Works with
Categories
How to build and run GCP Pub/Sub stream subscribers in Python under pystreams/ — the multi command (start at pystreams/src/pystreams/cmd/multi.py), the graminfra.pubsub publisher/subscriber library…. Gram Pubsub Python is an agent skill from speakeasy-api/gram.pubsub publisher/subscriber library, and the anyio runtime mirroring the Go gram streams process.
Gram Pubsub Python fits situations like: the Python runtime that consumes them; tasks that involve Event-driven systems.
Run `npx skills add speakeasy-api/gram --skill gram-pubsub-python -a claude-code`. Or copy the skill folder (.agents/skills/gram-pubsub-python in speakeasy-api/gram) into .claude/skills/gram-pubsub-python in your project. Claude Code loads it when a task matches its description.
Run `npx skills add speakeasy-api/gram --skill gram-pubsub-python -a codex`. Or copy the skill folder (.agents/skills/gram-pubsub-python in speakeasy-api/gram) into .agents/skills/gram-pubsub-python in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add speakeasy-api/gram --skill gram-pubsub-python -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/gram-pubsub-python, .gemini/skills/gram-pubsub-python, .github/skills/gram-pubsub-python and .opencode/skills/gram-pubsub-python in your project.
Going by SKILL.md and its folder, Gram Pubsub Python needs the command-line tools its instructions call (mise and uv). Our summary lists: Python 3.
SKILL.md contains no URLs. Its commands use uv, which can reach the network depending on how they are called. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Gram Pubsub Python is published under the AGPL-3.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 4.1k tokens (SKILL.md is roughly 17k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Gram Pubsub Python: Io Connectors (Kilo-Org/kilo-marketplace, 189 stars), AWS Serverless Eda (zxkane/aws-skills, 367 stars), Windmill Trigger Type Checklist (windmill-labs/windmill, 18k stars) and Opensource Guide Coach (calf-ai/calfkit-sdk, 149 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
speakeasy-api (a GitHub organization) maintains it in speakeasy-api/gram, which has 272 GitHub stars. The repository holds 39 skills in this directory. The repository was last updated on October 7, 2026.
Source: speakeasy-api/gram on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.