← Blog
2026-07-28 · 7 min read · 日本語

Sente — the coding agent CLI for teai.io,
benchmarked against Claude Code & Codex

We added Sente (先手, Japanese for "the initiative" in Go) to teai.io — a coding agent that runs in your terminal. It installs in one line and turns every teai.io model into an agent. Building it, we benchmarked it against Claude Code and Codex on the same task. The gap that showed up wasn't "which model is smarter" — it was "which client keeps its tools intact through the teai backend and actually finishes." Here's the measurement, and how we polished its accuracy.

winner
Sente
Only client that ran through teai without breaking. stable
runner-up
Claude Code
Works on glm-5.2, breaks on kimi-k3. model-dependent
rejected
Codex
Shell command corruption on every model. incompatible
TL;DR

Getting started

curl -fsSL https://teai.io/te | sh te # start the agent in the current directory te run "explain this repo" te max run "..." # max-performance mode = Kimi K3 (2.8T, 1M context) te -m teai/<model> # switch model (te models to list)

Sente is a thin launcher on top of OpenCode — we did not fork it. It just points OPENCODE_CONFIG at a teai.io-generated config, so it rides every upstream OpenCode improvement. The model catalog (95+ today) auto-syncs from /te/config on every launch.

Why "Sente"

teai.io reads as "te-AI" — te (手) means "hand" in Japanese. We carried that hand forward and named the agent after sente (先手), the Go term for taking the initiative. The agent makes the first move for you. "Always keep sente" — never give up the initiative. The command is short: te (a sente alias ships too).

Max-performance mode: te max = Kimi K3

Sente's default is glm-5.2, chosen for stability. The reason: Moonshot's flagship Kimi K3 (2.8T, 1M context) used to hang when streamed through OpenCode — no response came back. That has since been fixed in teai's streaming/fallback path, and Kimi K3 now works end to end. We re-verified it:

So we added te max. It keeps the cost-efficient default (glm-5.2) but flips to maximum performance in one word:

te max run "refactor this function and add tests" te max # interactive mode on K3
Kimi K3 costs $3 in / $15 out (per 1M tokens) — pricier than glm-5.2, but its 2.8T parameters and 1M context give it more raw horsepower on hard tasks. Daily driver: te (glm-5.2). When it counts: te max (K3).

Sente vs Claude Code vs Codex — same board

To keep it fair, we routed all three clients through the teai backend and had each audit our own code (a 25,000-line http.rs, Rust axum). The task: "find one .unwrap() that can panic on attacker-controlled input and write it to FINDING.md."

ClientBehavior via teaiResult
Sente (OpenCode)Sends OpenAI-compatible calls as-is. Zero conversion.ran, no break
Claude Codeteai converts its Anthropic tool_usebroke on kimi-k3
CodexCustom function-call + sandboxshell corruption

On teai/kimi-k3, Claude Code emitted a <ctrl46> control token as text and never fired its tools; Codex produced a broken shell command and died instantly with execvp() failed. Neither is "the client's fault" — they happen because teai's OpenAI-compatible conversion layer can't perfectly reproduce each vendor's tool format (Anthropic's tool_use, Codex's own format).

Structural takeaway: teai is OpenAI-compatible to begin with. So OpenCode-based Sente inserts no conversion layer and has nothing to break. If you're building on teai, Sente is the most stable choice — by design, not by luck.
Update (evening, 2026-07-28): Claude Code's <ctrl46> collapse was root-caused and fixed on the teai side after this benchmark ran (the real cause was tool_choice not being propagated — not Claude Code or Kimi K3). On re-testing in production, Claude Code + teai/kimi-k3 now writes the file correctly and the <ctrl46> collapse no longer reproduces. The benchmark above is a snapshot from that moment. Sente's structural edge — zero conversion layer, less to break — still holds.

The honest part: finding quality hits the model's ceiling

But "ran to completion" ≠ "good audit." On the shared model (glm-5.2), all three clients flagged a .unwrap() inside test code as a vulnerability — but attacker input never reaches a #[test] block, so it isn't one. That's not a client difference; it's the model's auditing ceiling. We cross-checked every finding against the real source to confirm.

Polishing: mechanical steps beat abstract rules

So we gave Sente a set of coding rules. On every launch it writes ~/.config/teai/sente-rules.md and injects it via the config's instructions field. Research on AGENTS.md best practices agrees: concrete, mechanically-followable steps beat abstract principles. So we turned the judgment into steps:

The result was split. Before the rules, the agent would write a guessed line number before reading; after, it reads the real code first and points at an actual .unwrap() lineread-before-write was measurably fixed.

But test-code exclusion did not get fixed, even with mechanical steps. Even after spelling out "skip it if the marker above is #[test]" and "assert-surrounded back-half = test," glm-5.2 keeps picking a .unwrap() inside the trailing test module. That's not a wording problem — it's the model's judgment ceiling.

Lesson: rules can correct procedure ("read before you write," "always deliver"), but they can't lift judgment ("is this reachable code?") past the base model's ability. For audits that need real precision, pick a stronger coding model (Sente switches with te -m).

Bonus: we fixed a production bug while prepping the comparison

Setting up the comparison, we found a bug where teai's /v1/chat/completions was dropping role:"tool" messages and the assistant's tool_calls (fixed and deployed). It broke the tool loop for every agent that round-trips tools — not just Sente.

Summary

Get a free API key and try Sente →
Sente (先手) · powered by OpenCode · shared model z-ai/glm-5.2 · all findings cross-checked against source · run in isolated git worktrees · 2026-07-28