Optimize a kernel with a coding agent#

This is the shortest path from “this kernel is slow” to a faster one that still passes your tests, and the one to start with. You describe the kernel in a sentence; a coding agent does the packaging, validation and integration, and checks with you before the two steps that matter.

The alternative, authoring the package yourself and running the search from the command line, is covered in Quickstart and gives you more direct control. Everything the agent produces is an ordinary task package, so you can switch to the manual path at any point.

What you need#

  • KernelFoundry with the MCP server, which is how the agent builds and benchmarks:

    pip install 'kernelfoundry[mcp,algo]'
    
  • An MCP-capable coding agent. The server speaks stdio and needs no editor, so Claude Code, Codex CLI, Cursor, GitHub Copilot in VS Code and any other MCP client all work.

  • A GPU and its toolchain. See the README.

Register the server with your agent. python -m kernelfoundry.mcp_server create_config generates a client config interactively, and the MCP server reference gives the literal form each client expects — they differ, and a config copied from the wrong one registers nothing. It also covers the choice between running locally and submitting to a server.

Tip

Point your agent at agent-workflow.md as well. It is the workflow contract the agent follows: the constraints, the checkpoints and the definition of done. It ships inside the installed package, next to the server module, so an agent can read it without network access.

Naming it once in your opening message is enough, but Claude Code and Copilot CLI can pick it up on their own, with no mention needed in your prompt:

python -m kernelfoundry.mcp_server install_agent --client claude    # or --client copilot

This writes it to wherever that client scans for a custom agent (~/.claude/agents/ or ~/.copilot/agents/ by default; add --scope project to install into the current project instead). The file carries the frontmatter both hosts need to route to it automatically — start a new chat session afterward for it to take effect.

For any other client, add a line pointing at agent-workflow.md to whichever instructions file it already reads — CLAUDE.md for Claude Code, AGENTS.md for Codex CLI, a rule under .cursor/rules/ for Cursor — so you don’t have to repeat it every session.

Start a session#

Paste this, filling in the two required parts. Everything commented out is optional; the agent infers it or asks:

Optimize <function> in <file path or upstream URL> for GPU with KernelFoundry.
# Optional (the agent will infer or ask if omitted):
# Language: <SYCL | OpenCL | CUDA>
# Benchmark shapes: <e.g. from upstream tests, or specific sizes>
# Build: <command>   Test: <command>   Env: <e.g. source /opt/intel/oneapi/setvars.sh>
# Constraints: <e.g. preserve macro-driven runtime flexibility>

A plain sentence works too. The agent asks for anything critical it cannot find.

A worked example#

Optimizing a real kernel from an upstream project:

Optimize the reusable_vectorized layer-norm OpenCL kernel from oneDNN
(https://github.com/uxlfoundation/oneDNN/blob/main/src/gpu/intel/lnorm/reusable_vectorized.cl).
Preserve the macro-driven runtime flexibility. Pull benchmark shapes from oneDNN's lnorm
tests, plus a few representative coverage shapes.

From that the agent freezes a faithful reference from upstream, gathers benchmark shapes (recording which came from real tests and which are for coverage), scaffolds the package, writes its USER_INSTRUCTIONS, validates locally, and stops to ask before submitting.

What to expect#

It works autonomously and tells you what it chose. It discovers the language, the reference behaviour, benchmark shapes from your tests and call sites, and your build and test commands by reading the codebase. Where it has to pick, it picks a sensible default and states it rather than asking you to fill in a form.

It writes the per-task guidance for you. The USER_INSTRUCTIONS block in the package is authored by the agent from your conversation. You edit it only to correct or add something, for instance to name an optimization strategy you already know pays off.

It stops at exactly two checkpoints:

  1. Before submitting a job, because that consumes compute and time. You get a summary of the package and its assumptions, then a go/no-go.

  2. Before integrating the result, because that edits your source.

Everything between those two points runs on its own. After each phase it reports what it did, the evidence, what it validated, and what it assumed.

What it produces is an ordinary task package (see Anatomy of a task package), so nothing here is a black box. If a run goes badly, Understanding results explains how to read the graph and work out why.

Integrate and verify the result#

Getting a faster kernel out of the loop is not the end. The number that matters is the end-to-end improvement in your application, not the isolated kernel.

Ask the agent to continue once you have picked a kernel from the results, and it will merge the optimized code back into your original implementation, preserving its semantics and generality, and surface any trade-off for your review rather than changing behaviour quietly. Then rebuild the full codebase, run its tests, and re-run your own benchmarks.

Important

Keep the reference implementation general. The optimized kernel is tuned for the benchmark shapes it was given, so before you ship it, confirm the edge cases and input shapes your software actually relies on still work.

Next steps#