KestrelDocs

Agents

What an agent works out about your repo settles into memory that outlasts the run. The next run starts where the last one stopped, not from zero.

Every run teaches the agent something: the build command that actually works, the test that needs a database, the folder nobody should touch. Kestrel keeps those facts per repo and hands the useful ones to the next run.

Fig. 1Agent memory
Agent memory vec3 memory(float t) { vec2 A = vec2(96.0, 96.0), S = vec2(236.0, 147.0), M = vec2(392.0, 150.0), D = vec2(420.0, 304.0 + 7.0 * sin(420.0 * 0.017 + 2.0 * 1.9) + 3.0 * sin(420.0 * 0.05 + 2.0)); if (t < 0.2) return vec3(A, 0.0); if (t < 0.7) return vec3(mix(A, S, ease((t - 0.2) / 0.5)), 1.2 * sm(0.2, 0.3, t)); if (t < 1.7) { float u = (t - 0.7) / 1.0; return vec3(mix(S, M, u) + vec2(0.0, 7.0 * sin(u * 9.0)), 1.2); } if (t < 3.0) { float u = (t - 1.7) / 1.3; float e = 1.0 - pow(1.0 - u, 2.4); return vec3(mix(M, D, e), 1.2); } return vec3(D, 0.0); } float field(vec2 p, float t) { float ph = TAU * t / T; float v = blob(p, vec2(96.0, 96.0), 26.0, 1.05); if (p.x > 164.0 && p.x < 676.0) { // short-term: a surface that churns, blobs welling up and sinking back float n = noise(vec2(p.x * 0.03 + 0.8 * cos(ph), p.y * 0.07 + 0.8 * sin(ph))) * 0.6 + noise(vec2(p.x * 0.07 - 0.5 * sin(ph), p.y * 0.12 + 0.5 * cos(ph))) * 0.4; v += exp(-pow(p.y - 147.0, 2.0) / 500.0) * (0.12 + 1.05 * smoothstep(0.35, 0.85, n)); // long-term: wavy strata of uneven thickness, older and fainter the deeper they lie, the top two sliding faster. // Each layer's tokens repeat every 12 columns and slide a whole number of those a cycle, so the loop closes. for (int i = 0; i < 5; i++) { float fi = float(i); float y = 224.0 + 40.0 * fi + 7.0 * sin(p.x * 0.017 + fi * 1.9) + 3.0 * sin(p.x * 0.05 + fi); float th = 9.0 + 5.0 * noise(vec2(p.x * 0.02, fi * 3.0)); float slide = 84.0 * (i < 2 ? 2.0 : 1.0) * t / T; float tok = step(0.18, hash(vec2(mod(floor((p.x + slide) / 7.0), 12.0), fi))); v += tok * exp(-pow(p.y - y, 2.0) / (th * th)) * (0.85 - 0.1 * fi); } } vec3 m = memory(t); vec2 dir = normalize(vec2(0.18, 1.0)); v += blob(p, m.xy, 11.0, m.z) + blob(p, m.xy - dir * 13.0, 8.0, m.z * 0.35 * step(1.7, t) * step(t, 3.0)); // it settles: a seam spreading along its layer, cooling into it if (t > 2.9) { float u = sm(2.9, 4.1, t); vec2 d = p - memory(2.99).xy; v += (1.0 - u) * 1.1 * exp(-(d.x * d.x) / pow(10.0 + 80.0 * u, 2.0) - (d.y * d.y) / 36.0); } return v; }
Notes from a run start as short-term memory. The ones that hold up across runs settle into long-term memory, and the next run reads them first.

How it fills

Agents save facts with the remember tool as they work. A fact is kept for the run first. If later runs find it true again, it moves to long-term memory; if a run proves it wrong, it is dropped.

Read it

Terminal
kestrel memory list --repo acme/web-app

build      npm run build:ci needs NODE_OPTIONS=--max-old-space-size=4096
tests      checkout.test.ts needs the payments mock on port 4010
avoid      Don't edit src/generated, it is rebuilt from schema.graphql
style      Use the Money type for prices, never number

Edit it

Memory is yours. Add what you know, and remove what is out of date.

await kestrel.memory.add("acme/web-app", { topic: "tests", text: "Run tests with --runInBand in CI" });
await kestrel.memory.forget("acme/web-app", { topic: "build" });
Note

On Team, memory is shared by everyone in the workspace. A fact one person's run learns helps every run after it.

Was this page helpful?

Open the dashboard