Proposal: Assess replacing the laptop Go forward proxy with Praxis — blocked on three upstream capabilities
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Idoneità per principianti
- 15/100
Direzione di ricerca
Read the assessment against Cortex main at 2362f7eb and Praxis v0.7.4 at a50e58e5, then inspect the referenced core/listener/forwardproxy, core/tlsbridge, and core/peerproc components. The issue recommends postponing migration until Praxis issues #781 and #782 are merged; its proposed migration is estimated at 35–52 engineer-weeks. Done means reassessing the migration after those upstream capabilities land.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Summary
This issue records an assessment of replacing the laptop Go forward proxy (cortex, run by agentop setup on 127.0.0.1:47600) with Praxis.
Conclusion: it is not possible today. Three capabilities the laptop depends on are missing from Praxis:
- HTTP
CONNECTand forwarding to the destination the client named. - HTTPS interception, meaning a TLS certificate minted per host from a local CA.
- Access, from a filter, to the client's TCP port.
Two of these have open Praxis issues. None has a merged design, and only one has an assignee. Once all three exist, the remaining work on the Cortex side is estimated at 35–52 engineer-weeks.
Scope is the laptop only. Kubernetes shapes (inbound reverse proxy, iptables capture, mTLS) are out of scope.
Assessed against Cortex main @ 2362f7eb, Praxis v0.7.4 (a50e58e5) and praxis-ai v0.7.0 on 2026-10-17. Prior issues: #504, #681 (closed 2026-10-05: on hold because Praxis has no forward or transparent proxy), #682.
What the laptop proxy does today
The laptop install runs only the forward proxy role. Per request it:
- Accepts plain
HTTP_PROXYrequests andHTTPS_PROXYCONNECTtunnels on one port. - Decrypts a tunnel with a certificate it mints for that host from
~/.cortex/ca. Whether to decrypt is decided per program: port, TLS peek, passthrough hosts, and a skip memory for programs that refuse the CA. - Attributes the request to a local program by looking up the owner of the TCP connection, then to a session from client headers, the program, or client affinity.
- Runs the outbound pipeline:
inference-parser,mcp-parser,a2a-parser,tool-prune, andinference-routerwhenagentop serverhas added a server. This includes:- body buffering;
- three SSE relay paths;
- redirects;
- resending a refused request with a changed model.
- Records request, response, denied, failure and tunnel events. These feed the session store, the cost ledger, the usage aggregator, the session archive, and the APIs on
:47601and:47602.
Size, non-comment Go lines:
| Component | Lines |
|---|---|
Forward proxy (core/listener/forwardproxy server and process) |
1,414 |
TLS bridge (core/tlsbridge) |
1,140 |
Process lookup (core/peerproc) |
632 |
Generic forwarding is a small part of this. Most of it is interception, attribution and recording.
Findings
Verified by running Praxis v0.7.4 on macOS arm64:
| Check | Result |
|---|---|
| Native release build | Succeeds: 2m43s, 21 MB binary |
| Health | /healthy returns 200 on admin.metrics_address |
curl --proxy http://127.0.0.1:<port> https://example.com/ |
405 Method Not Allowed. The Pingora fork rejects CONNECT unless allow_connect_method_proxying is set, and Praxis does not set it |
curl --proxy http://127.0.0.1:<port> http://example.com/ |
Forwarded to the configured cluster endpoint, not to example.com. There is no "connect where the client asked" routing |
Read from source, not exercised:
| Capability | Praxis v0.7.4 | Where |
|---|---|---|
| Certificate generation in the shipping binary | None. rcgen is only a dev-dependency (crates/protocol) or behind the opt-in bench-utils feature (crates/tls) |
crates/{protocol,tls}/Cargo.toml |
| Client address available to filters | IP only: client_addr: Option<IpAddr>, no port |
crates/filter/src/context.rs |
| Async response-body hook | No. on_response_body is a plain fn. Tracked in praxis-proxy/praxis#1105, which waits on a published Pingora release (praxis-proxy/praxis#1353) |
crates/filter/src/filter.rs |
| General ext_proc client | Removed from Praxis core in v0.4.1. The only one left, in praxis-ai, is scoped to llm-d and rejects every response_body_mode except none |
ai/integrations/llmd/ext-proc/src/lib.rs |
| Filter-registered admin endpoints | No. Admin routes are hard-coded (/api/kv/*, /api/pipelines, /api/log-level, /api/stats) |
crates/protocol/src/http/pingora/health/service.rs |
| Retry with a modified request | No. Retries resend the same request | router retry_policy |
| macOS in upstream CI | No workflow runs on a macOS runner | .github/workflows/ |
Blockers
All three are changes to Praxis itself; none can be done as a Cortex plugin or filter.
| # | Blocker | Laptop impact | Upstream status (2026-10-17) |
|---|---|---|---|
| B1 | CONNECT and destination-from-request forwarding | No agent traffic can pass | praxis-proxy/praxis#781: assigned to esnible, milestone v0.8.0 (due 2026-11-16; 150 open issues on it). Maintainer agreed scope: HTTP/1.1 only, a destination allowlist required. No proposal in praxis-proxy/enhancements and no PR |
| B2 | HTTPS interception (CA, per-host minting, cert cache, decrypted traffic re-entering the HTTP pipeline) | No parsing, cost, tool-prune or routing for HTTPS, which is all LLM traffic | praxis-proxy/praxis#782: unassigned, no comments, milestone v0.8.0 |
| B3 | Connection identity in filters (client port; per-connection state shared by a tunnel and the requests decrypted from it) | No program attribution, per-program decrypt decision, or self-traffic filter | Not filed |
Not blockers for this design:
- macOS: builds and runs.
- The synchronous response-body hook: avoided if the Go pipeline runs in-process; see Option A.
- Private and loopback upstreams: allowed by
insecure_options.allow_private_upstreams, which logs a warning.
Responsibilities
Praxis maintainers (praxis-proxy/praxis)
- Decide whether B1, B2 and B3 are in Praxis's scope.
- Own their design: the proposal process in
praxis-proxy/enhancements, review, merge, and long-term maintenance. - B2 needs a security decision only Praxis can make: CA key handling and trust distribution.
- Own the async response-body work (praxis-proxy/praxis#1105). It is not required by Option A.
Cortex team (rossoctl/cortex)
- Give Praxis written requirements for B1. Plain and CONNECT requests on one port, HTTP/1.1 is sufficient, and tunnel open/close hooks that carry byte counts.
- File B3 and the modified-request retry gap upstream, with the use cases.
- Decide whether Cortex offers engineers to implement B2 upstream. Today nobody owns it, and it is the critical path for the laptop.
- If B1–B3 land, everything in Work breakdown marked "Cortex".
- Until a decision to migrate, keep shipping the Go proxy. No Cortex release depends on Praxis.
praxis-ai maintainers (praxis-proxy/ai)
- No work is required for this migration.
- Optional, independent of it: Cortex could route to a praxis-ai instance as an inference backend for API translation (Anthropic Messages ⇄ Chat Completions). That uses praxis-ai as it ships today.
Joint
- praxis-proxy/praxis#781 already has an assignee on the Praxis side. Cortex's part there is requirements and testing against real agents: Claude Code, Codex, OpenCode, Bob.
Work breakdown (only once B1–B3 are available)
Design: Praxis owns the sockets, CONNECT and interception. The Go pipeline, session store and APIs are linked into the same binary as a C library, the reverse of how cortex-cpex links libcpex_ffi.a. agentop stays unchanged.
| Work | Code lives in | Estimate |
|---|---|---|
| CONNECT and forwarding to the client's destination (B1) | Praxis | 4–6 wk |
HTTPS interception (B2): CA create/renew, bundle.crt, minting, HTTP/1.1 and HTTP/2 on decrypted connections |
Praxis | 8–12 wk |
| Connection identity for filters (B3) | Praxis | 1–2 wk |
| Decrypt decision: ports, TLS peek, passthrough hosts, per-program skip memory, unread report | Cortex (Rust filter) | 3–4 wk |
| Program lookup port (macOS and Linux kernel tables), self-traffic filter, Go-on-macOS trust prediction | Cortex (Rust) | 2–4 wk |
| Go pipeline bridge: request, response, per-frame and end-of-request hooks; denials, body edits, redirect, resend | Cortex | 6–8 wk |
| Event recording: request, response, denied, failure and tunnel rows; byte counts; session-ID headers; affinity | Cortex | 3–4 wk |
| Packaging: one Go+Rust binary, darwin and linux release builds with cgo, supervisor and 502 fallback, existing CLI flags and ports | Cortex | 4–6 wk |
| agentop adjustments (small if flags, ports and CA paths are kept) | Cortex | 1–2 wk |
| Black-box parity tests against real agents. The existing Go proxy tests exercise Go internals and do not carry over | Cortex | 3–4 wk |
| Total | 35–52 engineer-weeks |
Of the total, 13–20 weeks is code in Praxis's own repository. Its schedule depends on Praxis review.
These are estimates from reading code, not from a prototype. The largest unknown is in B2: whether Praxis's Pingora fork can feed a decrypted connection back into its HTTP handling.
Benefits and costs
What adoption would bring:
- Proxy features maintained by others: WebSocket upgrade passthrough (Cortex strips
Upgradetoday), retries, circuit breakers, rate limiting. - Ecosystem alignment. The Praxis Policy Engine is the successor of CPEX, which
cortex-cpexlinks today. - Rust's safety profile and a FIPS build option.
What it would not change:
- Latency. A 2026-10-02 measurement put Cortex at about 1% of an LLM call's wall time, mostly parsing and recording, which would stay in Go.
- The plugins, session store or agentop. These stay in Go under this design.
Costs:
- The effort above.
- Two languages and cgo in every release build.
- Cross-repository review for proxy changes. The Go proxy, TLS bridge and process lookup had about 90 commits in the last three months, each shipped in a single PR.
- Upstream churn: Praxis went from v0.5.3 to v0.7.4 between 2026-08-19 and 2026-10-12.
Recommendation
- Do not start a migration now. Revisit when praxis-proxy/praxis#781 and praxis-proxy/praxis#782 are merged.
- Cortex, now:
- post laptop requirements on praxis-proxy/praxis#781;
- file B3 and the modified-retry gap;
- make an explicit decision on whether to offer engineers for praxis-proxy/praxis#782.
- Optional, independent of this issue: evaluate praxis-ai as an inference-router backend for cross-API server switching.
Open questions
- Is HTTPS interception (praxis-proxy/praxis#782) in Praxis's intended scope, and would Praxis accept an external implementation?
- Would Praxis expose connection-level identity (client port, per-connection state) to HTTP filters?
- Is a Go+Rust single binary acceptable for the laptop release, or must the release stay a static Go build?
References
- Praxis issues: praxis-proxy/praxis#781 (CONNECT), #782 (TLS interception), #1105 and #1353 (async response-body hook)
- Earlier Cortex work: #504, #681, #682;
cmd/cortex-praxisandcore/praxis(config converter, paused)
Assisted-By: Claude (Anthropic AI) [email protected]
- Lingua principale
- Go
- Stelle
- 16
- Fork
- 41
- Merge medio
- 11h 45m
- PR unite (30g)
- 246
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Nessun modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di rossoctl/cortex
-
UI shows costs for all sessions even when drilled into a sessionForse già presa @esnible l’ha presa 5 giorni fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
rossoctl/cortex#1116 · 2 commenti · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
Support mTLS for Session APIAperta
Difficoltà 5/5 Più di una settimana Idoneità per principianti 22/100
I maintainer di solito rispondono entro 1 giorno
-
Add a coding-agent demo with cpex policy enforcementForse già presa @araujof l’ha presa 3 giorni fa. Aperta
rossoctl/cortex#1428 · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
Release cortex-cpex binaries and add installer supportForse già presa @araujof l’ha presa 3 giorni fa. Aperta
rossoctl/cortex#1427 · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
Update the hr-cpex demo for CPEX 0.3Forse già presa @araujof l’ha presa 3 giorni fa. Aperta
rossoctl/cortex#1426 · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di rossoctl/cortex
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
oasdiff/oasdiff#1337 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
I maintainer di solito rispondono entro 1 giorno
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
dataiku/kiji-proxy#635 ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 67/100
hyperledger-firefly/signer#126 ·
-
agent-review-finding chore
Difficoltà 2/5 1-3 ore Idoneità per principianti 73/100
jordansmall/spindrift#5748 ·
I maintainer di solito rispondono entro 1 giorno