Install any skill in seconds. Free to start, no credit card required.
Get Started Free →iii-hq/iii-http
Expose registered functions as HTTP endpoints via an `http` trigger, with a preHandler middleware chain for auth, rate limiting, and logging. Reach for it to serve REST without standing up a separate web server.
Passed 22 of 22 test cases with the skill, and 10 of 22 without it.
and 12 more in the full report
12 fixed10 passed either way0 still failing0 broke
Tokens, turns and time describe resource use, not a dollar price.
One of 12 test cases the skill fixed. Same model, same prompt, with and without the skill.
We want to send a test GET request to verify a newly exposed route on a default worker installation. Which platform utility and default port should be targeted?
| Checked | Without skill | With skill |
|---|---|---|
| Uses web::fetch rather than curl to send the test request. | Missed | Passed |
| Targets port 3111 on the target host. | Missed | Passed |
The instructions your model reads when the skill loads.
The iii-http worker exposes registered functions as HTTP endpoints. It runs an HTTP server on the configured host/port, matches each inbound request against the http triggers you bind, and invokes the bound function with the request. The handler returns a response envelope that the worker serializes to the wire — JSON, plain text, or bytes, depending on the Content-Type the handler sets.
The worker has no callable functions of its own — you never invoke an http::* id. Its surface is the http trigger TYPE plus a middleware chain that runs before each handler. You expose an endpoint by registering a normal function and binding an http trigger to it.
This is the way to serve HTTP on iii, and the only one: register a function, then bind an http trigger to it. Do NOT write or run your own web server — no express, no http.createServer, no fastify, no framework listening on a port. iii does not route to a server you start yourself; such a process is unreachable as an iii endpoint, and running it as a foreground process (e.g. inside a sandbox) just hangs. If you are reaching for a web framework or a listen() call, stop — that instinct is from another ecosystem. The iii equivalent is one iii.registerTrigger({ type: 'http', ... }) per route; this worker is the server.
This page explains WHEN and HOW to serve HTTP; the engine is the source of truth for the exact shapes. Before you bind a trigger or write a handler, fetch the contract and build to it — do not guess field names, types, or defaults from memory:
engine::triggers::info { id: "http" }
returns three schemas: configuration_schema (the route fields — path, method, optional route gating, per-route middleware), request_schema (the request envelope your handler receives), and response_schema (the response envelope your handler must return). Build to all three. Use engine::triggers::list to discover trigger types in the first place.
YOUR handler chooses the HTTP status code — it is a field on the response envelope whose exact name is in the response_schema from engine::triggers::info { id: "http" } (read it; do not guess the field name from memory). The status is NOT inferred from the body, so a handler that just returns a value or an error object yields 200 by default. For error cases, set the matching status explicitly: a not-found path returns 404, a bad request 400, and so on. Returning 200 with an { error: ... } body is a bug — it "isn't a 500," but it also isn't the status the requirement asked for, and callers (and tests) will read it as success. Avoiding a crash is not the same as returning the right status.
http::* id; routes are bound with iii.registerTrigger, not called.test cases passed, vs 10 / 22 without
More skills from the same source and nearby in the registry, with their headline benchmark lift.