Mila Inference Server + Codex CLI: Local Agentic Loop #11
ToddThomson
announced in
Announcements
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
Mila Inference Server + Codex CLI: Local Agentic Loop
Date: 2026-05-15
Status: Proven / Experimental
Component:
Mila/Inference/ServerOverview
This document describes the design and implementation of a protocol translation layer that
enables Codex CLI to drive an agentic coding loop against a locally-hosted Llama 3.2 3B Instruct model served by the Mila Inference Server (MIS).
The result is a fully local, self-hosted agentic coding assistant: no OpenAI API key, no cloud dependency, no model modification required.
Architecture
Three parties interact; none required modification:
The Core Problem
Codex CLI sends tool definitions as full OpenAI JSON schemas —
$defs,oneOf, nestedproperties, boolean and array parameters. A 3B model cannot reliably parse and act on this structure.Llama 3.2 3B was instead fine-tuned on a simplified pythonic format:
MIS bridges the gap in both directions.
Inbound Translation: Tool Schema Distillation
protocols/openai/tool_bridge.py—build_tool_injection(tools)When Codex sends a request to
/v1/responses, the full tool schema array is distilled into a flat system prompt suffix the 3B model can act on:Tools with complex argument structures that cannot be expressed in flat
key=valueform are excluded. For Codex CLI this meansapply_patch,update_plan,spawn_agent, and others are suppressed, leaving onlyexec_commandandwrite_stdinwhich map cleanly.Outbound Translation: Tool Call Detection and SSE Emission
Buffered Streaming
Because the model emits a tool call token-by-token and we cannot know it is a tool call until generation completes,
_stream_responsesinroutes/factory.pysuppresses all per-token SSE delta events and buffers the full output. Thefinallyblock inspects the accumulated text and branches:function_callSSE event sequence Codex expects.output_textSSE event sequence.Parsing
tool_bridge.py—parse_tool_call(text)Detection order mirrors
Chat.ToolCallParserfrom the Mila Chat sample:<|python_tag|>prefix; slice past it if found.find("[")for bracket open,rfind("]")for bracket close.find("(")for paren open,rfind(")")for paren close —rfindis required to handle cmd strings that contain parentheses (e.g.main()).key="value"pairs usingrfind('"')for the closing quote, preserving embedded quotes in shell commands (e.g.<<"Hello\n").Known tokenization artifacts (
eexec_command,ejec_command) are corrected via a lookup table before the result is returned.SSE Event Sequence for a Function Call
Turn Continuation: Tool Result Handling
After Codex executes the tool, it sends a follow-up request to
/v1/responseswith the conversation history containingfunction_callandfunction_call_outputitems.parse_responses_requestconverts these into Llama role turns:function_callassistantfunction_call_outputtool"(no output)"messageuser/assistantWhen a
function_call_outputis present, tool injection is suppressed and the system prompt instructs the model to summarize and conclude rather than emit another tool call, breaking the loop cleanly.Limitations
int→inl). This is a model capacity ceiling, not a protocol issue. A larger model (Llama 3.1 8B, Qwen2.5-Coder-7B-Instruct) eliminates this._stream_responses.apply_patchnot supported: The Codexapply_patchtool uses a structuredcommandarray argument incompatible with flat key=value format. File writes useexec_commandwithprintfredirection instead.Relevant Files
protocols/openai/tool_bridge.pyprotocols/openai/responses.pyroutes/factory.pyfinallyVerified Configuration
llama-3.2-3b-instructserved by MIS on local GPUBeta Was this translation helpful? Give feedback.
All reactions