From fastloom-sdk
Use when the user wants to add a RabbitMQ subscriber, broker consumer, or signal handler to an existing fastloom service. Handles signals_module discovery, payload schema, retry/backoff configuration, and DLX-aware error semantics. Triggers on "add a subscriber", "consume a queue", "listen to a routing key", "handle a broker message".
How this skill is triggered — by the user, by Claude, or both
Slash command
/fastloom-sdk:add-rabbit-subscriberThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Scaffold a FastStream subscriber via `RabbitSubscriber.subscriber`, wire it into the project's `signals_module`, and produce the matching payload schema.
Scaffold a FastStream subscriber via RabbitSubscriber.subscriber, wire it into the project's signals_module, and produce the matching payload schema.
Look for:
app.py with signals_module=<pkg>.signals (or similar). Read it; if absent, the project may not have rabbit configured — confirm with the user before continuing.<pkg>/signals/ (or wherever signals live). Subscribers typically go under <pkg>/signals/consumer/<domain>.py; publishers under <pkg>/signals/producer.py. Follow whatever layout already exists.tenants.yaml should have RABBIT_URI under default:. If not, ask the user to populate it before testing.Ask in one round:
acme.user.created).UserCreated { user_id: UUID, email: str }), or "use an existing schema" with the import path.retry_backoff=True (default for production work) or False.<pkg>/signals/consumer/<domain>.py).<pkg>/schemas/<domain>.py (only if a new schema is needed)from pydantic import BaseModel
from uuid import UUID
class UserCreated(BaseModel):
user_id: UUID
email: str
If the payload needs alias mapping (e.g. broker uses bucket but the field is tenant), use Field(validation_alias="bucket") — do not patch the dict in the handler.
<pkg>/signals/consumer/<domain>.pyimport logging
from fastloom.signals.depends import RabbitSubscriber
from <pkg>.schemas.<domain> import UserCreated
logger = logging.getLogger(__name__)
@RabbitSubscriber.subscriber(
routing_key="acme.user.created",
retry_backoff=True,
)
async def on_user_created(payload: UserCreated) -> None:
logger.info("user created", extra={"user_id": str(payload.user_id)})
# business logic here
signals_moduleIf <pkg>/signals/consumer/__init__.py doesn't exist, create it (empty file is fine — init_signals walks subpackages). The App(signals_module=signals) declaration in app.py should already point at the parent package; no edit needed unless the package wasn't wired yet.
retry_backoff=True requires durable=True and auto_delete=False (both are the default). Don't override them.init_signals only walks subpackages, so handlers must live under a package (folder with __init__.py), not a sibling module.dict and validate inside the body. The whole point is pydantic at the broker boundary.payload.user_id).fastloom.signals.depends.RabbitSubscriber.publisher(...) to send messages back; don't construct aio_pika clients manually.raise — fastloom's exception middleware republishes to a delay queue with exponential backoff (5s → 10s → 20s → … up to 24h by default). The exception is re-raised after requeue for Sentry/OTel.docker compose ps rabbitmq (or whatever local broker the project uses).launch (or docker compose restart <service>).rabbitmqadmin:
import asyncio
from <pkg>.signals.producer import some_publisher # if there's a matching publisher
asyncio.run(some_publisher.publish({...}))
npx claudepluginhub aradng/fastloom --plugin fastloom-sdkCreates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.