Chalk Labs
Need help deploying kopf-conventions?
Chalk Labs sets up agents like this inside real teams: connected to your tools, tested on your data, with a human in the loop where it matters.
Install
Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.
npx agentmarket install skill/leroyguillaume-kopf-conventions
Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Use cases: design, devops
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
Permissions
What this skill can do and what it asks for, from its SKILL.md and code. Checked Oct 25, 2026.
- Tools
- No tools found
- Secrets
- None asked for
- Install scripts
- None found
Network hosts it talks to 1
codeload.github.com· found in install command
Files it touches
~/.claude/skills/kopf-conventions
What's inside
- Skill name
kopf-conventions- Description
- kopf mechanics for Python Kubernetes operators. TRIGGER when: code imports `kopf` or defines `@kopf.on.*`/`@kopf.timer` handlers; wiring `OperatorSettings`; emitting events from a Python operator; user asks why events don't show up, or about `kopf.event`, `kopf.TemporaryError` or `on.resume`. SKIP when: the operator is not kopf, or the question is framework-agnostic reconcile design (`kubernetes-operator-conventions`).
- License
- MIT
- Instructions
- 227 lines in SKILL.md · view on GitHub
Files (1)
- SKILL.md
SKILL.md (first lines)
# kopf conventions
kopf-specific implementation details for Python operators. The
framework-agnostic reconcile principles (always-requeue, idempotency,
finalizers, ownerReferences, field manager) live in
`kubernetes-operator-conventions` — this skill is the kopf wiring that those
principles compile down to, plus the sharp edges that bite in practice.
## Events & posting — the model you must get right
kopf has **two completely separate** ways an event reaches the cluster, gated
by **two different settings**. Confusing them is the #1 cause of "I had errors
but no events showed up on the resource".
1. **Explicit calls** — `kopf.event(body, type=..., reason=..., message=...)`
posts **iff `settings.posting.enabled` is True** (the default), whatever
`posting.level`. The shorthands also check the level: `kopf.info` needs
`level <= INFO`, `kopf.exception` `level <= ERROR`, and `kopf.warn`
`level <= WARNING` while ignoring `enabled`. Full control over
`type` / `reason` / `message`.
2. **Log-record posting** — kopf can mirror log lines made on the **object
logger** (`logger` injected into a handler) as events. This is gated by
**`settings.posting.loggers`**, which **defaults to `False`**. When off,
`logger.error(...)` / `logger.warning(...)` are logged but **never posted**.
`posting.enabled` does **not** turn this on — only `posting.loggers` does.
### The trap
> **`raise kopf.TemporaryError(...)` does NOT, on its own, post a Kubernetes
> event.** The error event you expect only exists if either (a) you post it
> explicitly with `kopf.event`, or (b) `settings.posting.loggers = True` so the
> framework's error log of the failure becomes an event.
Setting only `settings.posting.enabled = True` (a very common operator setup)
buys you nothing for errors raised via `TemporaryError`, because that path
surfaces through the **logger**, not an explicit `kopf.event`. Any docstring or
skill that says "kopf posts a Warning event for free when you raise
TemporaryError, provided posting.enabled is on" is **wrong** — it needs
`posting.loggers`.
kopf's log-to-event handler posts a record only when **all** of these hold: `posting.enabled`, `record.levelno >= posting.level`,
**`posting.loggers`**, and the record carrying a `k8s_ref` (i.e. it was logged
on the *object* logger, not a module-level `logging.getLogger(...)`).
### Surfacing errors as events — post them explicitly
- **Explicit lifecycle events: the failure event.** Post your own events at
the reconcile level — good `reason`s, one event per outcome, no framework
duplication. Wrap the handler:
```python
@kopf.on.create(GROUP, VERSION, PLURAL)
@kopf.on.resume(GROUP, VERSION, PLURAL)
@kopf.on.update(GROUP, VERSION, PLURAL)
async def reconcile(spec, body, name, logger, **_):
try:
changed = await _reconcile(spec, body, name, logger)
except Exception as exc:
logger.error("reconcile failed", extra={"cause": str(exc)})
kopf.event(body, type="Warning", reason="ReconcileFailed",
message=f"Reconcile failed: {exc}")
if isinstance(exc, kopf.TemporaryError):
raise
raise kopf.TemporaryError(f"reconcile failed: {exc}") from exc
if changed:
kopf.event(body, type="Normal", reason="Reconciled",
message="Desired state applied.")
```
Make the raised `TemporaryError` message carry the failing operation + cause
(e.g. `"creating the backing database failed: 500 ..."`) so the single
rolled-up `ReconcileFailed` event still names what broke; anything else is
wrapped, never re-raised raw, and the requeue holds either way. `_reconcile`
returns whether it changed anything: `on.resume` runs it for every CR at each
operator start, and a steady-state pass posts nothing.
- **Log-posted events: extra detail, never the failure event.** To add one
event per failing operation from the requeue chokepoint without plumbing
`body` everywhere, set all three in the startup handler:
```python
settings.posting.enabled = True
settings.posting.loggers = True
settings.posting.level = logging.WARNING # NOT the INFO default
```
Without raising the level off its `logging.INFO` default, **every** info line
becomes an event and floods the object. That level also silences
`kopf.info`, so post Normal events with `kopf.event(type="Normal")`, as the
wrapper above does. Even then the posted events carry
`reason="Logging"` (less descriptive than an explicit one), and the framework
may also post its own error log — expect duplicates.
Log posting never replaces the explicit Warning that
`kubernetes-operator-conventions` requires: it hangs on three settings and on
logging through the object logger, so a settings refactor or a module-level
logger drops the event without a sound. Don't half-set it (`enabled` without
`loggers`) and assume errors post — they won't.
### Cluster-scoped objects & other event gotchas
- **Events are namespaced; cluster-scoped CRs are not.** For a cluster-scoped
object kopf posts the event into the operator's *own* namespace
(`get_default_namespace()`, falling back to `default`), with `involvedObject`
pointing at the CR. `kubectl describe <clusterscoped>` still finds it by uid.
- **RBAC.** The operator's (Cluster)Role needs this rule; missing it is
silent (see next point):
```yaml
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
```
- **POST failures are swallowed.** `events.post_event` catches API errors and
only emits `logger.warning("Failed to post an event. ... Code: 403 ...")`.From leroyguillaume/claude, MIT.
More from leroyguillaume/claude
- 0.624score
adr-conventions
leroyguillaume
Architecture Decision Records in `docs/adr/`.
SkillAFreshness: A★ 7Claude Code +9 - 0.624score
api-conventions
leroyguillaume
HTTP/RPC API payloads in any language: DTOs, JSON casing, pagination, OpenAPI docs.
SkillAFreshness: A★ 7Claude Code +9 - 0.624score
architecture-conventions
leroyguillaume
ARCHITECTURE.md: the system as it stands, in the present tense.
SkillAFreshness: A★ 7Claude Code +9 - 0.624score
argocd-conventions
leroyguillaume
Argo CD objects in any GitOps repository.
SkillAFreshness: A★ 7Claude Code +9 - 0.624score
ci-conventions
leroyguillaume
Platform-agnostic CI pipelines: quality gate, Trivy scans, path filters, caching, releases.
SkillAFreshness: A★ 7Claude Code +9 - 0.624score
contributing-conventions
leroyguillaume
CONTRIBUTING.md: dev setup, tests, pre-commit and CI.
SkillAFreshness: A★ 7Claude Code +9 - 0.624score
dependency-update-conventions
leroyguillaume
Dependabot and Renovate configuration and their PRs.
SkillAFreshness: A★ 7Claude Code +9 - 0.624score
diagram-conventions
leroyguillaume
Diagrams in committed files: format and diagram type.
SkillAFreshness: A★ 7Claude Code +9 - 0.624score
docker-conventions
leroyguillaume
Dockerfiles: base images, multi-stage builds, non-root USER, hadolint and Trivy.
SkillAFreshness: A★ 7Claude Code +9 - 0.624score
documentation-conventions
leroyguillaume
Docs a human can maintain: one home per fact, links not copies.
SkillAFreshness: A★ 7Claude Code +9 - 0.624score
frontend-conventions
leroyguillaume
Frontend code: TypeScript, React, Biome, mobile-first.
SkillAFreshness: A★ 7Claude Code +9 - 0.624score
github-actions-conventions
leroyguillaume
GitHub Actions mechanics: workflows, pinned actions, SARIF, release notes, Releases, Pages.
SkillAFreshness: A★ 7Claude Code +9
Signals
- Stars
- 7
- Forks
- 3
- Open issues
- 0
- Last commit (this folder)
- Oct 4, 2026 (27 days ago)
From GitHub (fetched Oct 24, 2026).
Details
- License
- MIT
- Repository
- github.com/leroyguillaume/claude
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
- Source
- GitHubgithub-graphql
More from leroyguillaume
- 0.624score
api-conventions
leroyguillaume
HTTP/RPC API payloads in any language: DTOs, JSON casing, pagination, OpenAPI docs.
SkillAFreshness: A★ 7Claude Code +9 - 0.624score
architecture-conventions
leroyguillaume
ARCHITECTURE.md: the system as it stands, in the present tense.
SkillAFreshness: A★ 7Claude Code +9 - 0.624score
argocd-conventions
leroyguillaume
Argo CD objects in any GitOps repository.
SkillAFreshness: A★ 7Claude Code +9 - 0.624score
ci-conventions
leroyguillaume
Platform-agnostic CI pipelines: quality gate, Trivy scans, path filters, caching, releases.
SkillAFreshness: A★ 7Claude Code +9 - 0.624score
contributing-conventions
leroyguillaume
CONTRIBUTING.md: dev setup, tests, pre-commit and CI.
SkillAFreshness: A★ 7Claude Code +9 - 0.624score
adr-conventions
leroyguillaume
Architecture Decision Records in `docs/adr/`.
SkillAFreshness: A★ 7Claude Code +9
Done for you
Rather not set it up yourself?
Chalk Labs scopes, builds and runs agents for your team: the task audit, the eval harness, the integrations and the weekly ops report. Fixed scope, priced before we start.
See how we build AI agents →Read the case studies
Chalk Labs is a two-founder AI and growth studio. We build AI agents, CRMs and MVPs for Web3 and AI companies, and have shipped 50+ product and token launches.
- launches shipped
- 50+
- launches shipped
- media placements
- 500+
- media placements
- founders on every account
- 2
- founders on every account
Press we've placed: Forbes · CoinDesk · Decrypt · Cointelegraph · The Block
Rahil Jain, Co-founder, Chalk Labs. Ex-Goldman Sachs engineer. You talk to the person who builds it.
Get kopf-conventions running in your business
Tell us what you want to automate. A founder replies within one working day with a plan, not a pitch deck.
Cite this page
kopf-conventions skill. Agent Mart. https://agentmart.dev/skills/leroyguillaume-kopf-conventions (last updated 2026-10-24)