Skip to content
Yoann Frayce

Engineering notes

Experiments, and what broke

Smaller work that does not warrant a case study. Each note says exactly what I did: whether I built the thing, contributed part of it, or ran somebody else’s system and wrote down what happened. The verb is the first thing on the card, deliberately.

  1. OperatedJuly 2026

    Running an autonomous agent loop until it opened pull requests

    Three scheduled agents, a shared memory, and the operational failures nobody documents

    Attribution · The agent framework is Union.ai’s open-source Flyte agent loop. I did not write it. What follows is what I did with it: deploy it, run it end to end, debug it, and write down what broke.

    Three pipelines wake on a schedule and share a durable memory. A builder reads a GitHub issue and proposes files; a stricter verifier agent decides whether the work is correct and complete, and the pull request opens only if it passes, retrying up to three times before releasing the issue. A distiller reads the history of past runs and consolidates it into lessons the builder and reviewer read as context on their next run — which is the part that makes it a loop rather than three cron jobs. I wrote four issues. The agents opened three pull requests without any further prompting.

    • Below 10% free disk, kubelet marks the node under disk pressure and every pod stays pending. The only visible symptom is a connection reset on the API port — nothing in the error surface points at the disk.
    • A fine-grained GitHub token is read-only by default and needs contents, issues, pull requests and discussions all set to read/write. Closing an issue additionally requires pull-request write on top of issue write, which is not obvious from the permission names.
    • The shared memory needs two stores, not one. The save operation re-uploads the whole local tree, so with a single store a builder run silently overwrites lessons the distiller has just written.
    • Coordination between overlapping runs is best-effort rather than a lock, because GitHub comments have no atomic compare-and-swap. The builder therefore re-checks for an existing pull request immediately before opening one.
    • Flyte
    • Python
    • Docker
    • Kubernetes
    • GitHub API
    Repository ↗
  2. BuiltMarch – April 2026

    Wind forecasting with a bidirectional GRU

    Six years of station data, and a baseline that is harder to beat than it looks

    A bidirectional GRU forecasting wind speed 24 hours ahead from six years of hourly meteorological station records. The detail that matters is the target: wind direction is circular, so regressing on degrees asks the model to learn that 359° and 1° are adjacent. Decomposing into u and v components removes the discontinuity, and speed is recomputed from the predicted components afterwards. Two layers, 128 hidden units, MSE on standardised components, batch size 2048 on an RTX A5000, with the split done temporally rather than randomly so no future information leaks backwards.

    • 37,263 training sequences, 7,966 validation and 7,967 test, from an 18-feature hourly record split 70/15/15 in time.
    • Against a persistence baseline: MAE 2.68 km/h versus 2.70, RMSE 3.55 km/h versus 3.61 — a 0.8% and 1.6% improvement respectively.
    • That margin is small, and it is the honest headline. Persistence is a deliberately unglamorous baseline, and a model that clears it by one and a half percent has learned something real but not much. Reporting the gap rather than the raw error is what makes the number mean anything at all.
    • The prediction tracks the general shape of the wind well and visibly smooths the sharpest gusts — expected when forecasting from hourly data.
    Evaluation on the held-out test split: MAE 2.68 km/h for the GRU against 2.70 for persistence, RMSE 3.55 against 3.61, a 1.6 percent gain on RMSE. Below, predicted and actual wind speed plotted over 200 hours, and a bar chart comparing the two error measures.
    Measured on the held-out test split against a persistence baseline. The margin is small, and that is the result.
    • Python
    • PyTorch
    • pandas
    • scikit-learn
    Repository ↗
  3. Contributed toMay 2026

    A deterministic agent workflow over industrial incident reports

    Five typed steps, and a small model fine-tuned on the domain

    Attribution · A five-person hackathon team. I owned the agent workflow — the step pipeline, the typed schemas and the prompts. Teammates owned the fine-tuning and evaluation.

    Operator incident reports arrive as unstructured text and need to become a category, a severity, a likely root cause and a set of next actions. The workflow is deliberately a fixed five-step pipeline with a Pydantic schema at each boundary rather than a free-roaming agent, because the output feeds a maintenance decision and a schema violation should fail loudly rather than degrade quietly.

    • Python
    • Pydantic
    • LangChain
    • FastAPI
    Repository ↗
  4. BuiltFebruary 2026

    Buying a forecast only when it is worth more than it costs

    An agent that treats information as something it has to pay for

    An agent allocating capital in a simulated energy market, where the interesting decision is not the allocation but whether to buy a better forecast first. Before each epoch it computes the expected value of the premium signal and purchases one only when that value exceeds its price; otherwise it acts on the free, noisier signal. The policy is conditioned on risk tolerance, market regime and current drawdown, with a cash buffer that must survive the allocation before capital is deployed, and every decision emits a readable rationale rather than a bare action.

    • This is the earliest version of a habit that runs through everything since: make the system state why it did something, in terms a person can check, at the moment it decides.
    • The market is synthetic and there is a single test. The idea is the artefact here, not the implementation — which is why the repository is archived rather than presented as finished work.
    • It no longer runs as shipped. The hackathon’s testnet RPC has gone, and the settlement module both connects at import time and refuses without a private key, so the documented offline mode does not actually start. The capture above comes from a local run with settlement stubbed out; the policy, the expected-value calculation and the accounting are the repository’s own code. Software built against a temporary testnet has a shelf life, and this is what that looks like seven months on.
    The agent dashboard after thirteen epochs in a stress regime. The information-market panel shows the expected value of the premium signal at 0.26 EUR against a cost of 0.05, a net edge of 0.21, and the badge PREMIUM USED — the agent bought the forecast because it cleared its price.
    A real run of the archived app: expected value against cost, and the purchase that follows. Settlement is stubbed locally — see below.
    • Python
    • FastAPI
    • SKALE
    • Web3
    Repository ↗
  5. BuiltApril 2025

    An agent reviewing pull requests against rules it cannot argue with

    Early agent and MCP work, April 2025

    An n8n workflow that reviews GitHub pull requests against explicit API governance rules — no password in GET parameters, no email in a GET response, no plain HTTP GET permitted — with a Java Spring Boot MCP server exposing the codebase to the model. The rules are declarative and enumerated rather than described in a prompt, so a review either cites the rule it violated or says nothing.

    • Built around the Model Context Protocol in April 2025, which dates the instinct that later shows up everywhere else here: give the model the reading and keep the judgement in something enumerable.
    • Low-code orchestration, no tests, and no evaluation of whether the reviews were any good. It establishes a timeline rather than a result.
    • n8n
    • Java
    • Spring Boot
    • MCP
    • Docker
    Repository ↗
  6. BuiltMarch – April 2026

    Issuing real Apple Wallet passes

    Signing certificates, a pass generator and a manager app

    A loyalty system that issues genuine Apple Wallet and Google Wallet passes: a Node pass generator signing bundles against Apple WWDR certificates, a PostgreSQL backend migrated from SQLite once persistence in production stopped being optional, and an Expo manager app for scanning a customer card and incrementing visits. The signing chain is the part with no shortcuts — a pass either validates against Apple’s certificate chain and installs, or it silently does nothing.

    • Real signed `.pkpass` bundles were produced and installed, which is the only meaningful test of a pass pipeline.
    • No AI anywhere in it. It is here as evidence of platform integration work that has to be exactly right rather than approximately right.
    • Node.js
    • Expo
    • React Native
    • PostgreSQL
    • Apple PassKit