원클릭으로
codexcont-middleware
Continue-thinking middleware that detects and handles reasoning truncation in Codex/OpenAI Responses-compatible APIs
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Continue-thinking middleware that detects and handles reasoning truncation in Codex/OpenAI Responses-compatible APIs
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
| name | codexcont-middleware |
| description | Continue-thinking middleware that detects and handles reasoning truncation in Codex/OpenAI Responses-compatible APIs |
| triggers | ["set up CodexCont proxy","configure continuation middleware","handle reasoning truncation","proxy OpenAI Codex requests","extend thinking limits","configure CodexCont authentication","debug truncated reasoning","fold streaming responses"] |
Skill by ara.so — Codex Skills collection.
CodexCont is a Starlette-based proxy middleware that sits between coding agents and OpenAI Responses-compatible APIs. It automatically detects reasoning truncation (when reasoning_tokens == 518 * n - 2), silently continues the thinking process, and folds multiple upstream streaming responses into one coherent downstream response.
uv package manager recommended# Clone the repository
git clone https://github.com/neteroster/CodexCont.git
cd CodexCont
# Install dependencies
uv sync
# Copy and configure
cp config.example.toml config.toml
# Run the proxy
uv run python run.py
# Windows/Git Bash
.venv/Scripts/python.exe run.py
# Linux/macOS
.venv/bin/python run.py
Edit config.toml:
[server]
host = "127.0.0.1"
port = 8787
[upstream]
url = "https://chatgpt.com/backend-api/codex/responses"
mode = "header" # header | fixed
[auth]
mode = "passthrough" # passthrough | inject | passthrough_then_inject
access_token = ""
chatgpt_account_id = ""
[continue]
enabled = true
method = "commentary" # commentary | tool_pair
continue_tool_name = "continue_thinking"
max_rounds = 8
max_reasoning_tokens = 50000
tier_gate_low = 1
tier_gate_high = 100
[repair_followup]
mode = "off" # off | stateless | stateful
header mode (recommended): Allows per-request upstream override via Responses-API-Base header:
import httpx
response = httpx.post(
"http://127.0.0.1:8787/v1/responses",
headers={
"Responses-API-Base": "https://api.openai.com/v1",
"Authorization": f"Bearer {os.getenv('OPENAI_API_KEY')}"
},
json=payload
)
fixed mode: Always uses the configured upstream.url.
passthrough: Forward client auth headers only:
[auth]
mode = "passthrough"
inject: Override with configured credentials:
[auth]
mode = "inject"
access_token = "your-token-here" # Use env vars in production
chatgpt_account_id = "org-xxxxx"
passthrough_then_inject: Use client auth if present, fallback to config:
[auth]
mode = "passthrough_then_inject"
access_token = "your-fallback-token"
Security: The proxy will reject requests with Responses-API-Base header when inject mode would leak configured credentials to unknown URLs.
commentary (recommended): Uses hidden phase commentary to continue thinking:
[continue]
method = "commentary"
tool_pair: Legacy mode using synthetic tool calls:
[continue]
method = "tool_pair"
continue_tool_name = "continue_thinking"
[continue]
max_rounds = 8 # Maximum continuation rounds
max_reasoning_tokens = 50000 # Stop after this many reasoning tokens
tier_gate_low = 1 # Minimum tier n to trigger continuation
tier_gate_high = 100 # Maximum tier n to continue folding
import httpx
import os
import json
async def query_with_continuation(prompt: str):
"""Query through CodexCont proxy with automatic continuation."""
payload = {
"model": "gpt-4",
"messages": [
{"role": "user", "content": prompt}
],
"stream": True,
"reasoning": True # Enable reasoning to trigger continuation
}
async with httpx.AsyncClient() as client:
async with client.stream(
"POST",
"http://127.0.0.1:8787/v1/responses",
headers={
"Authorization": f"Bearer {os.getenv('OPENAI_API_KEY')}",
"Content-Type": "application/json"
},
json=payload,
timeout=300.0
) as response:
async for line in response.aiter_lines():
if line.startswith("data: "):
data = line[6:]
if data.strip() == "[DONE]":
break
event = json.loads(data)
# Handle reasoning items
if event.get("type") == "response.reasoning_item.delta":
print(f"Reasoning: {event.get('delta', {}).get('content', '')}")
# Handle message content
elif event.get("type") == "response.message.delta":
print(f"Output: {event.get('delta', {}).get('content', '')}")
# Final event with metadata
elif event.get("type") == "response.done":
metadata = event.get("response", {}).get("metadata", {})
rounds = metadata.get("proxy_rounds", [])
print(f"\nCompleted in {len(rounds)} round(s)")
for i, r in enumerate(rounds):
print(f" Round {i+1}: {r.get('reasoning_tokens')} tokens (tier {r.get('tier')})")
import requests
import os
def simple_query(prompt: str):
"""Simple synchronous query through proxy."""
response = requests.post(
"http://127.0.0.1:8787/v1/responses",
headers={
"Authorization": f"Bearer {os.getenv('OPENAI_API_KEY')}"
},
json={
"model": "gpt-4",
"messages": [{"role": "user", "content": prompt}],
"stream": True
},
stream=True
)
for line in response.iter_lines():
if line:
line_str = line.decode('utf-8')
if line_str.startswith("data: "):
data = line_str[6:]
if data.strip() != "[DONE]":
print(data)
import httpx
import os
async def query_different_endpoint(prompt: str):
"""Query a different Responses-compatible endpoint."""
async with httpx.AsyncClient() as client:
response = await client.post(
"http://127.0.0.1:8787/v1/responses",
headers={
"Responses-API-Base": "https://api.openai.com/v1",
"Authorization": f"Bearer {os.getenv('OPENAI_API_KEY')}"
},
json={
"model": "gpt-4",
"messages": [{"role": "user", "content": prompt}],
"stream": True
}
)
return response
payload = {
"model": "gpt-4",
"messages": [{"role": "user", "content": "Quick question"}],
"stream": True,
"reasoning": False # Disables folding/continuation
}
The middleware detects truncation when:
usage.output_tokens_details.reasoning_tokens == 518 * n - 2 (for integer n)tier_gate_low <= n <= tier_gate_high)max_rounds, max_reasoning_tokens)The final response includes proxy metadata:
{
"type": "response.done",
"response": {
"metadata": {
"proxy_rounds": [
{"reasoning_tokens": 516, "tier": 1},
{"reasoning_tokens": 1034, "tier": 2}
],
"proxy_billed_usage": {
"input_tokens": 150,
"output_tokens": 1550,
"reasoning_tokens": 1550
},
"proxy_stopped_reason": "clean_finish" # or "max_rounds", "max_tokens", etc.
},
"usage": {
"input_tokens": 150,
"cached_tokens": 0,
"output_tokens": 1550,
"reasoning_tokens": 1550
}
}
}
User Request
↓
CodexCont (round 1)
↓
Upstream API → 516 reasoning tokens (truncated)
↓
CodexCont detects 518*1-2, buffers output, continues
↓
CodexCont (round 2, reasoning replayed + "Continue thinking...")
↓
Upstream API → 250 reasoning tokens (complete)
↓
CodexCont flushes final output, reconstructs terminal event
↓
User receives single coherent stream
# Run test suite
uv run python tests/test_middleware.py
# Or with activated venv
.venv/Scripts/python.exe tests/test_middleware.py
Tests cover:
Check request format:
# Ensure these are set:
payload = {
"stream": True, # Must be true
"reasoning": True, # Or omit (defaults to true)
# ...
}
Verify configuration:
[continue]
enabled = true
tier_gate_low = 1 # Must be <= detected tier
tier_gate_high = 100 # Must be >= detected tier
With Responses-API-Base override:
# Use passthrough mode
[auth]
mode = "passthrough"
Inject mode rejecting requests:
Responses-API-Base when using inject mode to prevent credential leakspassthrough mode and send auth in request headersThis is expected behavior. Final answer text is buffered until the terminal round proves it's not truncated. Reasoning tokens stream live, but final message content waits for confirmation.
Check upstream URL:
[upstream]
url = "https://chatgpt.com/backend-api/codex/responses"
mode = "fixed"
Enable debug logging:
# In run.py or your client
import logging
logging.basicConfig(level=logging.DEBUG)
Currently expected: non-streaming requests pass through unchanged. Use "stream": true to enable continuation folding.
When using method = "tool_pair":
[continue]
continue_tool_name = "continue_thinking" # Must not conflict with real tools
If your request declares a real tool with this name, folding is disabled for safety.
For load balancing, run multiple instances on different ports:
# Instance 1
PORT=8787 uv run python run.py
# Instance 2
PORT=8788 uv run python run.py
Update config for port override:
import os
from middleware.config import load_config
config = load_config()
config.server.port = int(os.getenv("PORT", 8787))
[repair_followup]
mode = "stateful" # Tracks conversation state in-memory
Warning: State is process-local and not shared across instances. Not recommended for production load-balanced deployments.
Edit middleware/codex.py:
# For commentary method
CONTINUE_MARKER = "Continue your reasoning from where you left off..."
# For tool_pair method
def _build_tool_pair_continuation(...):
# Customize tool description/arguments
pass
from langchain.chat_models import ChatOpenAI
llm = ChatOpenAI(
openai_api_base="http://127.0.0.1:8787/v1",
model="gpt-4",
streaming=True
)
response = llm.invoke("Complex reasoning task...")
from openai import OpenAI
client = OpenAI(
base_url="http://127.0.0.1:8787/v1",
api_key=os.getenv("OPENAI_API_KEY")
)
stream = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": "Think deeply about..."}],
stream=True
)
for chunk in stream:
print(chunk.choices[0].delta.content or "", end="")
Configure in editor settings:
{
"openai.api.baseUrl": "http://127.0.0.1:8787/v1",
"openai.api.key": "${OPENAI_API_KEY}"
}
config.tomlpassthrough auth mode: Simplest and most secure for developmentproxy_rounds metadata: Understand how many continuation rounds are triggeredmax_rounds and max_reasoning_tokenscommentary method: More reliable than legacy tool_pair approachConvert attached object images into code-only, animation-ready procedural Three.js models through guided sculpting workflow
Create and manage AI video storyboard projects with automated asset generation through Codex Storyboard workspace
Desktop manager for OpenAI Codex CLI with prompt injection, provider switching, and TOML/Auth visualization
Inject unrestricted developer mode instructions into Codex CLI (GPT-5.5) to bypass content filters
Install and use TradingCodex to build Codex-native investment research workflows with fixed-role agents, order approval gates, and local Django service plane
Install and manage local Markdown instruction files for Codex CLI using model_instructions_file configuration