Skip to content

Add authenticated endpoint and inference client for AI-powered Friendly Error Messages - #1083

Merged
mwtrew merged 16 commits into
mainfrom
add-fem-api-endpoint
Nov 2, 2026
Merged

mwtrew merged 16 commits into
mainfrom
add-fem-api-endpoint

Conversation

@mwtrew

@mwtrew mwtrew commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Status

Points for consideration:

  • Security:
    • New endpoint is behind ai_friendly_errors feature flag, and requires the user to be logged-in
  • Performance
    • Inference response is not streamed at the moment - this may change in future.
    • I have set reasoning: { effort: :none } on the OpenAI client, which makes the response a lot faster but potentially less accurate. This was useful for local testing, but may be less important with a different inference API.
    • The OpenAI client supports automatic retries with exponential backoff - I have disabled this to avoid holding Puma threads open for a long time.

What's changed?

  • Adds a POST endpoint /friendly_error_messages that requires message, trace, runtime and code keys in the request body, and returns an AI-generated friendly error message, or a hardcoded sample message if BYPASS_FEM_INFERENCE=true.

What's not changed?

Steps to perform after deploying to production

Eventually we will want to configure FEM_INFERENCE_API_URL and FEM_INFERENCE_API_KEY in other environments, but that is blocked on https://github.com/RaspberryPiFoundation/digital-editor-issues/issues/1920.

Guide to testing inference locally with Ollama

  1. Get Ollama running locally: https://formulae.brew.sh/formula/ollama

  2. Set the following in .env:

FEM_INFERENCE_API_URL=http://localhost:11434/v1/
FEM_INFERENCE_API_KEY=''
BYPASS_FEM_INFERENCE=false
BYPASS_OAUTH=true
  1. Enable the ai_friendly_errors feature flag
$ rails c
app(dev):001> Flipper.enable(:ai_friendly_errors)
  1. Start the API, then hit the endpoint with curl:
curl -i -X POST http://localhost:3009/api/friendly_error_messages \
  -H "Authorization: Bearer abc123" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "NameError: name '\''prnt'\'' is not defined",
    "trace": "Traceback (most recent call last):\n  File \"main.py\", line 1, in <module>\nNameError: name '\''prnt'\'' is not defined",
    "runtime": "skulpt",
    "code": "prnt(\"Hello world\")"
  }'

You should get something like:

{"fem":"It looks like Python doesn't recognize the word `prnt` because it isn't a standard command or function known by that name. It might be worth checking if you accidentally typed \"print\" wrong, since the correct built-in function to display text is spelled with an \"n\" in that spot. Looking at line 1 of your code would likely reveal this small spelling detail."}

@cla-bot cla-bot Bot added the cla-signed label Oct 30, 2026
@github-actions

github-actions Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

Test coverage

94.18% line coverage reported by SimpleCov.
Run: https://github.com/RaspberryPiFoundation/editor-api/actions/runs/41470718922

@mwtrew
mwtrew temporarily deployed to editor-api-p-add-fem-ap-2our6z October 30, 2026 13:40 Inactive
@mwtrew
mwtrew temporarily deployed to editor-api-p-add-fem-ap-2our6z October 30, 2026 14:34 Inactive
@mwtrew
mwtrew temporarily deployed to editor-api-p-add-fem-ap-2our6z October 30, 2026 15:15 Inactive
@mwtrew
mwtrew temporarily deployed to editor-api-p-add-fem-ap-2our6z October 30, 2026 15:21 Inactive
@mwtrew
mwtrew temporarily deployed to editor-api-p-add-fem-ap-2our6z November 2, 2026 10:06 Inactive
@mwtrew
mwtrew temporarily deployed to editor-api-p-add-fem-ap-2our6z November 2, 2026 10:07 Inactive
Uses the OpenAI client SDK to call a real inference service.

The values in .env.example work for a local Ollama instance.
@mwtrew
mwtrew force-pushed the add-fem-api-endpoint branch from 645140a to fbf4e38 Compare November 2, 2026 10:25
@mwtrew
mwtrew temporarily deployed to editor-api-p-add-fem-ap-2our6z November 2, 2026 10:25 Inactive
@mwtrew
mwtrew temporarily deployed to editor-api-p-add-fem-ap-2our6z November 2, 2026 10:28 Inactive
@mwtrew mwtrew changed the title Add authenticated endpoint for FEM Add authenticated endpoint and inference client for AI-powered Friendly Error Messages Nov 2, 2026
This is is an abridged version of https://github.com/RaspberryPiFoundation/slm-evaluation/blob/main/corpus/prompt.yml.

It is not complete or final, but it suggests how to send different system prompts.
@mwtrew
mwtrew temporarily deployed to editor-api-p-add-fem-ap-2our6z November 2, 2026 11:13 Inactive
The default timeout is 600 seconds, which will hold up Puma threads for too long.
@mwtrew
mwtrew temporarily deployed to editor-api-p-add-fem-ap-2our6z November 2, 2026 12:12 Inactive
@mwtrew
mwtrew temporarily deployed to editor-api-p-add-fem-ap-2our6z November 2, 2026 13:15 Inactive
@mwtrew
mwtrew marked this pull request as ready for review November 2, 2026 13:16
@macroscopeapp

macroscopeapp Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Approvability

Verdict: Needs Human Approval

Macroscope's review found this PR requires human approval — The new endpoint sends learner code and error traces to a configured inference service, with authentication, feature gating and bounded requests. Confirm production remains disabled until the service destination and learner-data handling are acceptable; deployment settings are not established by the example configuration.

Needs human approval because:

  • approvability is in preview mode for this repository, so Macroscope does not approve PRs here

You can add or adjust custom eligibility rules. Learn more.

@mwtrew
mwtrew temporarily deployed to editor-api-p-add-fem-ap-2our6z November 2, 2026 13:22 Inactive
@mwtrew
mwtrew temporarily deployed to editor-api-p-add-fem-ap-2our6z November 2, 2026 13:32 Inactive
@mwtrew
mwtrew temporarily deployed to editor-api-p-add-fem-ap-2our6z November 2, 2026 13:33 Inactive
Comment thread config/routes.rb Resolved

@zetter-rpf zetter-rpf left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great, I've added a couple of small suggestions

This gives us a more prescriptive API for checking if a flag is enabled given the user -
the bare `Flipper.enabled?` can accept any actors as params, so it can be easy to use it
inconsistently by mistake.

`enabled_for_user?` returns true if the flag is enabled for the user, their school, or everyone.
@mwtrew
mwtrew temporarily deployed to editor-api-p-add-fem-ap-2our6z November 2, 2026 15:15 Inactive
@mwtrew
mwtrew temporarily deployed to editor-api-p-add-fem-ap-2our6z November 2, 2026 15:21 Inactive
@mwtrew
mwtrew merged commit 775a10e into main Nov 2, 2026
10 checks passed
@mwtrew
mwtrew deleted the add-fem-api-endpoint branch November 2, 2026 15:27

This branch was previously deployed

1 inactive deployment
editor-api-p-add-fem-ap-2our6z — e6ce2e1f Deployed Nov 2, 2026 by mwtrew
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants