Questi sono gli strumenti di knowledge base che una chat di Claude o Claude Code riceve dal server MCP di osFoundry. Sono stati recuperati con un tools/list non autenticato il 2026-11-08 e ridotti a ciò che conta qui:
{"name": "search_knowledge_base",
"description": "Search current published articles in one granted knowledge base. Results cite the article ID and updated time; this is a live database read.",
"inputSchema": {"required": ["knowledge_base_id", "query"],
"properties": {"query": {"type": "string", "minLength": 2, "maxLength": 200},
"limit": {"type": "integer", "minimum": 1, "maximum": 20}}},
"annotations": {"readOnlyHint": true}}
{"name": "read_knowledge_article",
"description": "Read one current published article by ID from a granted knowledge base and return a stable citation.",
"inputSchema": {"required": ["knowledge_base_id", "article_id"]},
"annotations": {"readOnlyHint": true}}
{"name": "edit_knowledge_article",
"description": "Replace article content and optionally its title. Supply the version from read_knowledge_article; concurrent changes are rejected.",
"inputSchema": {"required": ["knowledge_base_id", "article_id", "content",
"expected_version", "idempotency_key"]},
"annotations": {"readOnlyHint": false, "destructiveHint": true, "openWorldHint": true}}
{"name": "poll_resource_events",
"description": "Resume from an event sequence for one granted channel, Note, knowledge base, record, or session.",
"inputSchema": {"required": ["resource_type", "resource_id"],
"properties": {"after_sequence": {"type": "integer", "minimum": 0},
"limit": {"type": "integer", "minimum": 1, "maximum": 100}}},
"annotations": {"readOnlyHint": true}}
Se leggi le descrizioni insieme, il design viene fuori da solo. Un risultato di ricerca porta un ID articolo e un orario di aggiornamento. Una lettura restituisce "a stable citation" (una citazione stabile). Una modifica richiede "the version from read_knowledge_article" (la versione ottenuta da read_knowledge_article). E c'è un log di eventi per ogni knowledge base che si può riprendere da un numero di sequenza. L'orario di aggiornamento nella citazione e la versione che una modifica deve indicare sono, in pratica, lo stesso tipo di valore: il client di osFoundry per questi strumenti, connected-cloud-tools.ts nell'app desktop, tipizza expected_version di edit_knowledge_article come format: date-time.
Quindi una citazione non è solo un riferimento per chi legge. È un timbro di versione che l'agente può verificare in seguito e, subito dopo la lettura, restituire come token di compare-and-swap. Qui sotto c'è cosa porta questo approccio, misurato su una ricostruzione.
Cosa dovrebbe contenere una citazione?
Tre candidati:
| Citazione | Regge a un cambio di titolo | Mostra che il contenuto è cambiato | Usabile come versione per la modifica |
|---|---|---|---|
| Titolo dell'articolo | no | no | no |
| ID dell'articolo | sì | no | no |
| ID dell'articolo + orario di aggiornamento | sì | sì | sì, se recente |
Il titolo è quello che un lettore umano vuole vedere, quindi viene la tentazione di citare solo per titolo e cercarlo di nuovo più tardi. Così però si nota solo un articolo rinominato o rimosso. Un articolo il cui testo è cambiato sotto lo stesso titolo sembra a posto. L'ID risolve le rinomine. È l'orario che rende verificabile se una citazione è obsoleta.
La ricostruzione
Qui non gira nessun binario di Claude. kb_store.py implementa i quattro strumenti su sqlite con i nomi reali, gli argomenti obbligatori e i limiti (query di 2–200 caratteri, limit fino a 20 per la ricerca e fino a 100 per gli eventi). Solo gli articoli pubblicati sono ricercabili o leggibili. Le strutture JSON sono quelle della ricostruzione, perché il server reale le restituisce solo a un client autenticato. La citazione è {knowledge_base_id, article_id, updated_at}. Ogni salvataggio scrive un evento {sequence, type, article_id, updated_at}, e edit_knowledge_article è un compare-and-swap su updated_at con una tabella di idempotenza, in un'unica transazione BEGIN IMMEDIATE.
sim.py simula una giornata di supporto:
- 400 articoli, 120 domande e 300 salvataggi fatti da persone nell'arco di 8 ore.
- La popolarità segue una curva di Zipf (s = 0.9). I primi 10 articoli ricevono il 36.7% delle domande e il 36.7% dei salvataggi, perché gli articoli su cui le persone fanno domande sono quelli che le persone continuano a correggere.
- Dei salvataggi, l'85% cambia il contenuto, il 10% cambia anche il titolo e il 5% annulla la pubblicazione.
- Per ogni domanda, un "Claude" scriptato chiama
search_knowledge_base, legge i primi due risultati conread_knowledge_articlee tiene entrambe le citazioni. - Ogni ora controlla in tre modi tutte le citazioni date fino a quel momento.
Seed 1–5, Python 3.9.6 su un Apple M1, solo stdlib. L'esecuzione completa richiede 25.7 s.
Quanto velocemente diventano obsolete le citazioni?
Cinque seed, 120 risposte ciascuno, due citazioni per risposta:
| Ora | Citazioni finora | Obsolete | Risposte con una citazione obsoleta | Trovate dal solo controllo sul titolo |
|---|---|---|---|---|
| 1 | 152 | 24 (15.8%) | 56.6% | 5 su 24 |
| 2 | 298 | 61 (20.5%) | 61.7% | 17 su 61 |
| 4 | 580 | 165 (28.4%) | 72.1% | 56 su 165 |
| 6 | 914 | 250 (27.4%) | 69.4% | 84 su 250 |
| 8 | 1,200 | 369 (30.8%) | 80.2% | 152 su 369 |
A fine giornata quasi un terzo di tutte le citazioni punta a un articolo cambiato da quando Claude l'ha letto, e quattro risposte su cinque hanno almeno una citazione del genere. "Cambiato" non vuol dire "sbagliato": una modifica può toccare un paragrafo che la risposta non ha mai usato. Ma nessuno può dire quale sia senza guardare, ed è l'orario nella citazione a dire a Claude dove guardare.
La popolarità spiega la maggior parte del fenomeno. L'esecuzione di controllo distribuisce gli stessi 300 salvataggi in modo uniforme su tutti i 400 articoli: diventa obsoleto il 13.9% delle citazioni (167 su 1,200) e il 46.7% delle risposte (280 su 600). Più la tua knowledge base viene usata, più gli articoli che Claude cita sono proprio quelli in corso di modifica.
Il controllo sul solo titolo ha trovato 152 delle 369 citazioni obsolete, il 41.2%. Erano tutti cambi di titolo o pubblicazioni annullate. Una modifica del contenuto non la vede mai.
Rileggere ogni articolo citato o interrogare il log?
Costo dei controlli orari nell'arco della giornata, sommato sui cinque seed (40 controlli):
| Strategia | Chiamate | Dati restituiti | Per controllo |
|---|---|---|---|
| Ricercare di nuovo ogni titolo citato | 2,426 | 3,342 KiB | 60.6 chiamate, 83.5 KiB |
| Rileggere ogni articolo citato | 2,264 | 3,445 KiB | 56.6 chiamate, 86.1 KiB |
poll_resource_events da un cursore |
40 | 153 KiB | 1.0 chiamata, 3.8 KiB |
Entrambe le strategie basate sull'ID hanno trovato esattamente le stesse 369 citazioni obsolete della ground truth. Lo script lo verifica con un assert a ogni controllo. La differenza è il costo. Rileggere cresce con il numero di articoli citati e paga ogni volta il loro testo completo. Il polling cresce con il numero di modifiche avvenute. Meno di 100 modifiche all'ora stanno in una pagina, quindi ogni controllo è stato una sola chiamata, e Claude rilegge solo gli articoli che si sono mossi. Il cursore è un unico intero da conservare tra un turno e l'altro. Prima del primo poll, l'agente ha bisogno di una sequenza da cui partire: 0 oppure l'ultima sequenza che ha salvato insieme alle sue citazioni.
Cosa succede quando Claude modifica usando la versione di una citazione?
Il secondo esperimento usa la stessa giornata. Dopo ogni risposta, Claude modifica il primo articolo che ha citato passando l'updated_at della citazione come expected_version, dopo un ritardo. Cinque seed, 150 modifiche per ritardo:
| Ritardo dopo la lettura | Rifiutate, versione cambiata | Rifiutate, non più pubblicato | Nuovo tentativo dopo una nuova lettura |
|---|---|---|---|
| 20 s | 0 (0.0%) | 0 | — |
| 15 min | 30 (20.0%) | 2 | 30 su 30 salvate |
| 1 h | 57 (38.0%) | 3 | 57 su 57 salvate |
| 4 h | 85 (56.7%) | 14 | 85 su 85 salvate |
Una citazione è una buona versione per la modifica per qualche secondo e una pessima dopo un'ora. I rifiuti sono il sistema che funziona: ognuna di quelle scritture avrebbe altrimenti sostituito il testo più recente di una persona con contenuto costruito su una lettura più vecchia. La soluzione è meccanica. Rileggere, riapplicare la modifica a ciò che c'è, scrivere con la nuova versione. Ogni nuovo tentativo è andato a buon fine.
È stata verificata anche la chiave di idempotenza. Dopo ogni modifica riuscita, la stessa chiamata con la stessa chiave è stata inviata di nuovo. 409 su 409 hanno restituito il primo risultato marcato come replay e non hanno scritto nessun nuovo evento.
Perché osFoundry risponde solo da articoli pubblicati?
Perché una citazione dovrebbe puntare a qualcosa che una persona ha deciso essere una risposta. Nell'app desktop, la scheda Publishing di un articolo dice "Published articles are used by this workspace's AI assistant and search. They are not visible outside the workspace." (gli articoli pubblicati sono usati dall'assistente AI e dalla ricerca di questo workspace e non sono visibili al di fuori). Le bozze sono invisibili a search_knowledge_base e read_knowledge_article, e un articolo di cui si annulla la pubblicazione sparisce da entrambi alla chiamata successiva. Nella ricostruzione, annullare la pubblicazione scrive un evento come qualsiasi altro salvataggio. 19 delle 600 modifiche ritardate qui sopra hanno trovato un articolo non più pubblicato, e il controllo segnala quella citazione come sparita, non come cambiata.
Perché lo strumento di modifica è marcato come open-world?
edit_knowledge_article è l'unico strumento di knowledge base con openWorldHint: true. Il suo effetto non resta nella conversazione. L'articolo salvato è quello da cui risponderanno subito dopo tutti gli altri assistenti e le ricerche del workspace. Le annotazioni dicono al client che questa chiamata cambia uno stato condiviso, e Claude Code chiede conferma prima di eseguirla, a meno che tu non l'abbia autorizzata. osFoundry aggiunge un proprio controllo quando una chat collegata lavora dalla schermata Knowledge Base dentro l'app: connected-browser-run.ts chiede l'approvazione per ogni scrittura cloud e non offre un permesso valido per tutta la sessione.
Se lo implementi tu
- Metti una versione nella citazione, non solo un ID. Usa lo stesso valore che il tuo strumento di modifica accetta come
expected_version, così una sola lettura ti dà entrambe le cose. - Tieni un log di eventi per ogni knowledge base con una sequenza monotona, e lascia che l'agente riprenda da un numero. Un intero di stato lato client sostituisce la rilettura di tutto ciò che ha mai citato.
- Rispondi solo da contenuti pubblicati e registra l'annullamento della pubblicazione come evento, così una citazione può tornare come "sparita" e non solo come "diversa".
- Fai delle modifiche un compare-and-swap sull'intero contenuto con una chiave di idempotenza obbligatoria. Di' al modello, nella descrizione dello strumento, di rileggere prima di modificare, perché una versione presa da una citazione vecchia di un'ora fallisce circa quattro volte su dieci.
- Marca lo strumento di scrittura come destructive e open-world, e mantieni anche dal tuo lato un'approvazione per ogni chiamata.
Cosa intende osFoundry per retrieval e grounding è spiegato nella sua voce di glossario sul RAG. Come sono organizzate le sue knowledge base è descritto nella pagina sulle knowledge base.
Top comments (0)