Kenapa osFoundry mengirim schema record di setiap halaman yang di-list Codex? A developer rebuilt osFoundry's MCP record tools so that each listed page returns the channel's schema alongside item previews, since the edit tool's input schema only exposes values as a generic object and cannot describe per-channel fields. The writeup measures four levels of validation-error detail, arguing that API messages naming the failing field are usually enough for a self-correcting retry, and compares a before_id cursor against offset paging plus an event log for resuming later. Berikut tool record channel yang didapat koneksi Codex CLI dari osFoundry https://osfoundry.io/id , seperti yang di-list oleh endpoint MCP publiknya. Tool ini diambil dengan tools/list tanpa autentikasi pada 2026-11-09 dan dipangkas ke field yang relevan di sini: {"name": "list record items", "description": "List the schema and a bounded page of item previews from one granted record channel. Use read record item for the complete values.", "inputSchema": {"required": "record channel id" , "properties": {"record channel id": {"type": "string"}, "before id": {"type": "string"}, "limit": {"type": "integer", "minimum": 1, "maximum": 50}}}, "annotations": {"readOnlyHint": true}} {"name": "read record item", "description": "Read one item by ID from a granted record channel and return its current version.", "inputSchema": {"required": "record channel id", "item id" }} {"name": "edit record item", "description": "Update validated fields in one record item. Supply the version from read record item; concurrent changes are rejected.", "inputSchema": {"required": "record channel id", "item id", "values", "expected version", "idempotency key" , "properties": {"values": {"type": "object"}}}, "annotations": {"readOnlyHint": false, "destructiveHint": true}, "securitySchemes": {"type": "oauth2", "scopes": "osfoundry:write" } } Perhatikan values . Isinya {"type": "object"} , tidak lebih. Schema tool tidak bisa memberi tahu key apa saja yang dimiliki sebuah channel, mana yang field Select, atau apa yang boleh diisi ke Points, karena semua itu beda per channel dan berubah saat seseorang mengedit tab Schema. Satu-satunya tempat Codex bisa mengetahuinya adalah baris pertama deskripsi tool list: schema ikut kembali bersama halaman. Sisa tulisan ini mengukur apa yang didapat dari situ, pada sebuah rebuild, beserta dua pilihan lain di empat tool yang sama: cursor before id alih-alih offset, dan event log untuk kembali lagi nanti. Tipe field-nya tetap. packages/shared/src/types/record.ts di frontend osFoundry mendefinisikan RecordChannelFieldType sebagai 16 tipe: text, number, date, boolean, email, phone, url, select, multi select, currency, percentage, rating, relation, file, json, dan formula. Setiap field membawa is required , is unique , dan config khusus per tipe: max length untuk text, min / max untuk number, max stars untuk rating, options untuk dua tipe select, expression untuk formula. Select adalah yang paling sering menjebak agent. Sebuah opsi berbentuk {value, label, color} . Yang disimpan adalah value, sedangkan label adalah yang dilihat orang. RecordDataGrid.tsx me-render sel select dengan options.find o = o.value === params.value dan fallback ke String params.value di chip yang pudar kalau tidak ada yang cocok. Jadi kalau pengecekan yang longgar membiarkan "In progress" masuk ke field yang value-nya in progress , grid akan menampilkan sesuatu yang kelihatan benar padahal salah: tanpa warna, dan tidak terlihat oleh apa pun yang mengelompokkan atau memfilter berdasarkan value. Model yang hanya pernah melihat label di grid, atau pesan dari seseorang, akan mengirim label. Harus ada yang menolak. API record osFoundry membalas panggilan yang gagal dengan {ok: false, error: {message}} . Tool record milik aplikasi desktop untuk agent di dalam aplikasi src-tauri/src/record tools.rs meneruskan pesan itu ke model apa adanya, dan komentarnya menjelaskan alasannya: pesan API "names the field that failed validation, which is usually enough for a self-correcting retry." Unit test-nya memakai values.status is not a valid option sebagai contoh. "Usually enough" itu bisa diukur. Rebuild ini mencoba empat tingkat detail dalam sebuah penolakan: {"error": "validation failed"} Ini tingkat "values", persis dari hasil run: {"error": "validation failed", "fields": {"key": "status", "message": "values.status must be one of the option values, got \"In progress\"", "allowed": "new", "triaged", "in progress", "fixed", "wont fix" }, {"key": "owner", "message": "values.owner must be one of the option values, got \"Aiko\"", "allowed": "aiko", "mika", "ren" }, {"key": "points", "message": "values.points must be between 0 and 13, got 20", "min": 0, "max": 13}, {"key": "due", "message": "values.due must be a date as YYYY-MM-DD, got \"Friday\""}, {"key": "age days", "message": "values.age days is a formula field and is computed, not written"} } String-string ini milik rebuild. Hanya penamaan values.