Engineering Platform › Shared module · See it on the architecture map
A queued, tool-using AI loop - a worker claims a job, asks to run one of a fixed list of tools, gets a result back, and keeps going until it has an answer. Originally built just for Tourney's own AI feature, then pulled out into its own portable package so a second app could reuse the real, hardened logic instead of rebuilding it from a written description. Nothing in the package imports the app around it - copying the folder in is the entire integration.
An app creates a job and drops it in a queue. A worker - a separate process, possibly on hardware the app doesn't fully control - checks in, claims the job, and starts talking to a model. When the model wants information it doesn't already have, the worker sends back a tool_call: the name of a specific action and its arguments, never a request to just "go look something up" in the open. The app checks whether that call is actually allowed, runs it if so, and sends the result back as a tool_result. That exchange repeats until the model is ready to answer, and only the app ever writes the tool_result - a worker cannot post one for itself, which is what makes the event log a record of what actually happened rather than what a worker claims happened.
app agentkit model host
--- -------- ----------
creates a job ------------> queue
claim
executes tools <-- tool_call -- worker loop --prompt--> model
(app owns the data) <--calls--
\--- tool_result -->
Authorization comes from the job's own recorded type - never from the job's input, and never from the list of tools that got sent to the worker. That list is advisory: it tells the worker which tools to offer the model, and it grants nothing. A worker that edits or forges it gains nothing either way - an unregistered tool name is refused outright, and a registered one still runs under the app's own handler and the app's own argument schema, regardless of what the worker asked for.
Two checks run before any tool executes, in a fixed order, and neither one substitutes for the other:
tool_call has to carry the worker_id that actually claimed this job. Missing, empty, the wrong type, or a job with no recorded claimant at all - every one of those fails closed rather than being treated as "probably fine."A worker's own identity is checked but not treated as a secret - it says which worker is asking, it doesn't prove the request is legitimate. That proof comes from a separate bearer token, checked before any of this logic even runs.
Every one of these fails toward "stop the job," never toward "let it keep going and hope":
| One tool call's arguments | 8 KB, or refused |
| One tool's result | 32 KB, then truncated and logged as such |
| Tool calls in one job | 20, then refused |
| One tool handler's real running time | 10 seconds, then it's treated as failed |
A separate watchdog expires a job that stops checking in at all, so a worker that crashes mid-loop doesn't leave a job stuck "running" forever with nothing watching it.
Tourney's own AI feature runs on this. GetSeen's does too, now - a real second caller, not a hypothetical one, which is the actual proof a "reusable" package is reusable rather than just generalized-sounding. It's easy to conflate this with AI Worker Boundary, since both trace back to the same original Tourney work: Spark Worker Kit is the transport that talks to FOMX.ai's own GPU hardware - the polling, the claim logic, the usage tracking for that one specific machine. agentkit is one layer up from that: the job queue and the tool-calling security boundary itself, independent of which model or which hardware actually answers the prompt.