01Introduzione
TeraBrain NX è una piattaforma per progettare, eseguire e governare sistemi agentici completi: agenti LLM, canali d'ingresso, dati, codice TypeScript e integrazioni MCP descritti come un unico grafo versionato. Lo stesso grafo si costruisce dall'editor visuale, conversando con il Builder, oppure da un assistente esterno (Claude, Codex, Cursor) collegato via MCP.
Questo manuale descrive il modello di esecuzione, ogni tipo di nodo, l'SDK dei workspace, la sicurezza e l'osservabilità. È scritto per sviluppatori full stack, architetti e AI engineer che devono progettare grafi di produzione, scrivere codice nei workspace o integrare la piattaforma con sistemi esistenti.
Convenzioni. I nomi di campi, porte, funzioni e percorsi sono in monospace e restano in inglese, come appaiono nella console e nelle API. I nomi delle etichette dell'interfaccia sono tra virgolette ("Uses tools"). Gli esempi di codice sono TypeScript.
Cosa ottieni dalla piattaforma, in sintesi:
- Agenti con tool, deleghe e passaggi di conversazione tra agenti, su modelli OpenAI‑compatibili (cloud o privati).
- Canali pronti: web app, Telegram, email, telefono (SIP + voce), scheduler, server MCP.
- Dati gestiti: database MySQL, file storage, libreria di skill in formato Agent Skills.
- Codice proprio in TypeScript, con repository git per nodo, eseguito in cloud o su macchine on‑premise.
- Governance: ruoli, secrets, OAuth, SSO Microsoft Entra, versioni del grafo, audit completo e tracing di ogni conversazione.
02Modello concettuale
Un grafo è un insieme di nodi tipizzati collegati in due modi: tool edge (chi offre strumenti a chi li usa) e flow edge (chi avvia conversazioni e chi le risponde). Solo gli agenti ragionano; tutti gli altri nodi portano conversazioni agli agenti o danno loro strumenti.
Nodi e porte
Ogni nodo ha un nodeId univoco nel grafo, un type (agent, webapp, connector, database, filestorage, sandbox, mcp, email, telegram, voice, …) e quattro famiglie di porte:
| Famiglia | Etichetta in console | Direzione | Esempi di portId |
|---|---|---|---|
exposes |
Provides tools | offre tool | rw, ro, admin, functions, developer, sandbox |
consumes |
Uses tools | riceve tool | tools |
sources |
Starts conversations | avvia flussi | delegate, handoff, agent, inbound, outbound |
sinks |
Answers | riceve flussi | sink ("Conversations"), calls, in |
Una porta exposes può offrire meno di quanto il nodo sappia fare. Un database, per esempio, espone admin (DDL incluso) e rw (solo DML): il grafo decide chi riceve quale livello di privilegio.
Tool edge e flow edge
Nel JSON del grafo gli archi sono due liste separate:
"toolEdges": [
{ "consumerNodeId": "agent", "consumerPortId": "tools",
"providerNodeId": "sandbox", "providerPortId": "sandbox" }
],
"flowEdges": [
{ "sourceNodeId": "webapp", "sourcePortId": "agent",
"sinkNodeId": "agent", "sinkPortId": "sink" }
]
Regole strutturali da tenere a mente:
- Una conversazione termina sempre su un agente.
- Una telefonata raggiunge un agente solo attraverso un nodo
voice. - I tool arrivano alla porta
consumescon il loro nome. Quando più provider offrono lo stesso nome, il runtime lo disambigua con il nodo e la porta come suffisso (es.query_TB_Academyequery_TB_Academy_rw,getFile_storage_ro).
Documento del grafo e versioni
Il grafo è un documento JSON con graphId, name, organizationId, nodes, toolEdges, flowEdges, ui e revision. I campi computed* (URL pubblicati, tool esposti con i relativi JSON Schema, stato dei database) sono scritti dalla build e non vanno editati.
Ogni modifica, da editor, Builder o MCP, produce una nuova revisione registrata a nome di chi l'ha fatta. Le scritture usano concorrenza ottimistica: una modifica basata su una revisione superata è rifiutata con HTTP 409. rollback riporta il grafo a una versione precedente; oltre il punto in cui un nodo con dati è stato aggiunto, serve conferma esplicita.
Build e runtime
"Save" applica la nuova revisione e ricostruisce i nodi cambiati; il resto del grafo continua a girare. "Rebuild node" ricostruisce un singolo nodo. Un nodo resettato o rimosso distrugge i propri dati secondo il tipo (database svuotato, repository git e container del workspace ricreati, conversazioni dei canali perse): la documentazione di ogni tipo lo dichiara nella sezione "What removing or resetting it destroys".
03Mappa della console
La console è organizzata in tre aree: Build (progettare e sviluppare), Run (usare e osservare), Organization (amministrare). Il selettore in alto a sinistra cambia organizzazione o mostra "All organizations".
| Area | Sezione | Cosa contiene |
|---|---|---|
| — | Home | Chat rapida con un agente, prompt al Builder, app e agenti (con preferiti), conversazioni recenti, grafi con stato |
| Build | Build | Il Builder: chat a sinistra, grafo disegnato in tempo reale a destra, toggle "Tool activity" |
| Build | Graphs | Elenco grafi con stato; New graph (vuoto o da recipe), Import…; per grafo: Rebuild, Export…, Duplicate…, Copy id, Delete |
| Build | Code | Tutti i workspace TypeScript: ultimo commit, stato, modifiche non committate; browser file, history, git clone, "Clone in VS Code" |
| Build | Skills | Libreria di skill: scrittura, import zip, download |
| Build | Files | Tutti i file storage: upload drag&drop, cartelle, condivisione con link a scadenza (ore) |
| Build | Databases | Tutti i database MySQL: Schema (colonne, chiavi, FK, diagramma), Query (Run, Run selection, Explain, history), Data |
| Build | Docs | Documentazione di ogni tipo di nodo e recipe; "What the Builder is told" |
| Run | Agents | Chat con gli agenti, raggruppati per grafo; conversazioni con filtro "Only mine" e tool activity |
| Run | Apps | Le web app pubblicate, con il livello d'accesso (public, organization, group) |
| Run | Calls | Registro chiamate telefoniche per grafo |
| Run | Scheduled tasks | Task dello scheduler ed esiti di ogni esecuzione |
| Run | Logs | Flows, Tool calls, Graph, Changes, Person (vedi §15) |
| Organization | Organization | Settings (provider LLM, model profile), Members, Secrets, Variables, Connections, Identity |
| Organization | Sites | Macchine on‑premise registrate con l'agente TeraBrain NX |
| — | Profile | Identità esterne (link Telegram), password, token per assistenti MCP, secrets, connections e variabili personali |
L'editor di grafo
L'editor mostra i nodi come schede con le porte raggruppate per famiglia e il numero di tool per porta ("Tools · 20 from file-storage, sandbox…"). La legenda distingue le linee: tratteggiate per i tool, continue per le conversazioni, e le chiamate telefoniche.
- Create node apre una procedura in tre passi (Choose a node → Kind → Set up), con le categorie Agents, Channels, Data & knowledge, Code & execution, Integrations, Telephony, Patterns e il toggle "Show advanced".
- Si collega trascinando da una porta o con il suo "+". Un clic su nodo o porta apre il pannello di configurazione a destra, con i pulsanti Fade, Rebuild node e Delete.
- Checks elenca i problemi bloccanti e i suggerimenti "Worth knowing" (es. una porta che offre tool che nessuno usa), con le azioni "Show me" e "Let an agent use them".
- Try it apre una chat di prova con un agente del grafo, con tool activity visibile.
- Il menu "…" offre Add area (rettangoli titolati per raggruppare), Auto layout, Fit to view, View JSON (con Apply, Download, Upload…), Export…, Duplicate…
- Undo/redo agiscono sulle modifiche locali; nulla è applicato fino a "Save".
04Agenti
L'agente è l'unico nodo che ragiona: legge la conversazione, sceglie i tool, risponde. Senza tool può solo conversare. Riceve conversazioni sulla porta sink ("Conversations") da canali, altri agenti, codice o dalla sezione Agents della console.
Campi principali
| Campo | Chi lo legge | Note |
|---|---|---|
nodeId |
sistema | Obbligatorio, breve e parlante (support-agent) |
| Name | persone | Nome mostrato; default = nodeId |
| What it does, in one line | persone e client MCP | Mai letto dal modello dell'agente; letto dagli assistenti che lo raggiungono via server MCP |
instructions |
modello | System prompt, una lista di paragrafi. Qui va il lavoro dell'agente |
modelProfile |
runtime | Un model profile dell'organizzazione; vuoto = default dell'organizzazione |
| Who may talk to it | console | public, organization (default) o group. Riguarda solo la chat della console: ogni canale ha il proprio controllo d'accesso |
Se l'organizzazione non ha alcun model profile, l'agente risponde con un eco fisso: utile per testare il cablaggio. In quella modalità un messaggio che inizia con /handoff passa la conversazione lungo la porta handoff, e /attach rimanda gli allegati ricevuti.
Parametri avanzati
| Parametro | Default | Effetto |
|---|---|---|
| Look at images | off | Tool viewResource per guardare immagini su richiesta invece di includerle in ogni chiamata; richiede un modello multimodale |
| Listen to audio | off | viewResource trascrive l'audio; con STT a scelta tra elevenlabs, wyoming, openai |
| Transcribe incoming audio | on | Trascrive l'audio di un messaggio prima che il modello lo legga (limite 25 MB) |
| Tell the agent who it is talking to | on | Aggiunge nome ed email del membro al system prompt |
| Tell the agent the date and time | on | Aggiunge data, ora e fuso d'inizio conversazione |
| Let it split work into subtasks | on | Tool runSubtask: istanza vuota dello stesso agente, stessi tool, nessun contesto, conversazione figlia |
| See its own conversations | off | Tool listConversations e history sulle conversazioni figlie |
| Allow public file links | off | Tool linkResource: link pubblico a un file della conversazione, scaricabile senza sessione |
| Tool rounds per turn | 64 (max 200) | Round di tool per turno prima di fermarsi senza risposta finale |
| Tool timeout | 600 s | Oltre, il modello viene informato che il tool non ha risposto |
| Model timeout | 600 s | Durata massima (o silenzio massimo in streaming) di una chiamata al modello |
Orchestrazione multi‑agente
Un agente collabora con altri attraverso due porte sources:
- Delegate a task (
delegate): offre il toolassignTask. L'agente affida un compito all'agente collegato in una nuova conversazione e attende la risposta, oppure la lascia in background. Timeout di default 600 s (taskTimeoutSeconds). - Hand off (
handoff): offre il toolhandoff. La conversazione intera passa all'altro agente, che risponde da quel momento in poi.
Ogni porta ha una description: è ciò che il modello legge sull'agente all'altro capo, quindi decide quando delegare. Il flag Inherit User (default on) fa sì che la conversazione delegata appartenga allo stesso utente. Per aggiungere un collaboratore si aggiunge una porta per agente, ognuna con la sua descrizione.
La porta Edit this agent (developer) espone readInstructions ed editInstructions: permette a un agente sviluppatore di leggere e riscrivere le istruzioni di un altro.
Errori tipici
- Istruzioni che promettono ciò che nessun tool permette.
- Il compito scritto nella descrizione di una riga, che il modello non legge.
- Un agente rivolto al pubblico con tool che modificano o cancellano dati.
05Canali
I canali portano conversazioni agli agenti. Ognuno ha il proprio controllo d'accesso, indipendente da "Who may talk to it" dell'agente.
Web app (webapp)
Un connector (§7) che serve anche HTTP: i file in public/ e l'handler esportato da app.ts sono pubblicati a un indirizzo dell'ambiente. Ha tutte le porte del connector (functions, developer, tools, agent). "Who may open the app" vale public (default), organization o group; l'identità del visitatore arriva sempre negli header della richiesta. Nome e descrizione compaiono nella sezione Apps; l'indirizzo viene scritto sul nodo dopo la build. Dettagli di sviluppo in §11.
Telegram bot (telegram)
Ogni messaggio al bot diventa una conversazione; le risposte tornano in chat con testo, file, foto e messaggi vocali. Si crea il bot con @BotFather e si imposta botToken, preferibilmente come {"secretRef": "TELEGRAM_BOT_TOKEN"}. Unica connessione: source → sink dell'agente.
- "Who the bot answers" limita il bot ai membri: ciascuno collega il proprio account dal profilo con
/link CODE. /resetapre una nuova conversazione; "Start a new conversation every day" lo fa a mezzanotte.- Lo stesso token su due nodi o due grafi: riceve messaggi solo l'ultimo costruito.
Mailbox (email)
La posta in arrivo diventa una conversazione, una per thread; le risposte partono nello stesso thread. La porta inbound va all'agente che risponde; la porta tool mail ("Send & search mail") dà gli strumenti per scrivere, cercare e leggere a qualunque agente.
| Variante | Configurazione |
|---|---|
| Hosted by TeraBrain NX | receive: {"kind":"hosted","localPart":"nome"}, send: {"kind":"hosted"}; indirizzo attivo alla build |
| Gmail / Google Workspace | Connection Google con set "Gmail via IMAP/SMTP", senza password |
| Microsoft 365 | Connection Microsoft 365 con set "Mail"; supporta mailbox condivise |
| IMAP + SMTP | Qualunque provider o server proprio, con utente e password |
Una mailbox lavora senza nessuno collegato: con una connection personale va indicato in "Member whose account is used" di chi è il token. "Access (advanced)" accetta solo posta autenticata di membri o di un gruppo. Sulla connessione mail il campo allow limita i destinatari.
MCP server (mcp)
È la porta d'ingresso per assistenti esterni (Claude, ChatGPT, Claude Code, Cursor) come custom connector. Due porte, anche insieme:
- Tools to serve (
tools, consumes): i tool collegati sono serviti con i loro nomi. - Agent to talk to (
agent, source): il client può assegnare un compito a un agente, continuare la conversazione e ritrovare le conversazioni passate.
Dopo la build il nodo mostra l'indirizzo: si incolla nelle impostazioni connector dell'assistente, oppure si apre nel browser per le istruzioni (Claude Desktop può installarlo come estensione). L'indirizzo equivale a una password: chi lo possiede può fare tutto ciò che tool e agente consentono. Un nuovo apiKey (avanzato) lo cambia. Il campo instructions (avanzato) è ciò che il modello del client legge sul server.
Questo nodo espone un grafo. Per far costruire e sviluppare grafi a un assistente si usa invece il token personale del profilo (§12).
Voice (voice)
Dà voce a un agente testuale al telefono: ascolta, parla, trasferisce e chiude. Porte: calls (sink, chiamate da linea, orari, menu, routing o interno), agent (source, l'agente che parla) e control (tool "Call controls" per lo stesso agente). L'agente vede una conversazione normale più una riga che indica chi chiama.
- STT e TTS configurabili; la variante ElevenLabs usa Scribe e una voce ElevenLabs e chiede solo la chiave.
- Hang up è sempre disponibile; il transfer solo verso chi è nella
directory(nome, numero o interno, scopo).transfers.allowsulla portacontrolapre anche numeri esterni. - Istruzioni scritte per il parlato: frasi brevi, niente liste né Markdown. Tool veloci: mentre girano il chiamante sente un riempitivo.
Scheduler
L'orologio del grafo. Tre porte: agent (source, l'agente a cui un task scrive; il testo del task è il messaggio), tools (consumes, tool eseguibili direttamente senza agente) e schedule (exposes, tool per far pianificare all'agente i propri follow‑up, con limiti di frequenza, numero e durata). I task si scrivono nella sezione Scheduled tasks o da un agente, non nel nodo; ogni esecuzione è registrata. A quell'ora nessuno è collegato: il task usa solo risorse dell'organizzazione o dell'account fissato nel nodo.
06Dati e conoscenza
Tre nodi gestiti dalla piattaforma danno agli agenti e al codice uno stato persistente: un database relazionale, un file storage e una libreria di skill. In tutti e tre la description del nodo è contesto per il modello: dice cosa contiene, e l'agente la legge prima di cercare.
MySQL database (database)
Un database MySQL (InnoDB) creato e mantenuto dalla piattaforma, interrogabile da agenti e codice e consultabile dalla sezione Databases.
| Porta | Privilegi | Uso tipico |
|---|---|---|
admin ("Full access") |
DDL + DML | Agente sviluppatore o codice che crea lo schema |
rw ("Read & write") |
SELECT, INSERT, UPDATE, DELETE | Agenti e app in esercizio |
ro (aggiuntiva) |
sola lettura | Analisi, reporting; con tableFilter (orders, order_*) |
Ogni porta espone due tool:
schema: tabelle raggiungibili dalla porta con colonne, tipi, chiavi e foreign key, letti in tempo reale.query(sql, params, asResource): una sola istruzione per chiamata, con placeholder eparams. Restituisce al massimo 100 righe inline; un risultato più grande è allegato completo come risorsa CSV. ConasResourcetorna solo il CSV, da passare a un altro tool senza leggerlo.
Il tableFilter è applicato alla build: dopo aver creato le tabelle che nomina, si ricostruisce. Reset = database svuotato con stessi account e porte; rimozione = dati distrutti. Una richiesta di DDL su rw viene rifiutata.
Skill library
Istruzioni operative (procedure, checklist, stile, con file allegati) che l'agente carica solo quando servono. L'agente tiene in contesto l'elenco di una riga delle skill e legge per intero quella pertinente: una libreria lunga non costa finché non si usa. Il formato è Agent Skills (SKILL.md con name e description), lo stesso usato da Claude.
ro("Use skills") per gli agenti che le seguono;rw("Use & write skills") per un agente che impara o per un bibliotecario istruito in chat.- Una voce con
tagsvede solo le skill con uno di quei tag: una libreria, uno scaffale per agente. - La
descriptiondi ogni skill decide quando si apre: deve dire quando si applica.
Una procedura nelle istruzioni dell'agente viene letta a ogni turno e non è riutilizzabile; come skill, no.
File storage (filestorage)
Un drive condiviso: gli agenti salvano e leggono file, le persone li aprono dalla sezione Files o dall'indirizzo del nodo.
| Porta | Tool |
|---|---|
rw ("Read & write files") |
listFiles, getFile, putFile, deleteFile, moveFile, shareFile, unshareFile |
ro ("Read files") |
listFiles, getFile |
- Le cartelle sono percorsi (
reports/2026/q3.pdf).listFilesrestituisce al massimo 500 voci, conrecursivee flagtruncated. - Una porta aggiuntiva può avere
root(una cartella) eshare: false. shareFilecrea un link pubblico con scadenza (default una settimana).- Un file letto entra nella conversazione come risorsa; un file ricevuto da una mailbox o da una chat può essere salvato senza codice.
- Limiti di dimensione per file e per drive nei campi avanzati.
Non dare rw a un agente pubblico: potrebbe cancellare o condividere file.
07Codice ed esecuzione
Quattro nodi portano codice ed esecuzione nel grafo: il connector (funzioni TypeScript come tool), la sandbox (una shell Linux per l'agente) e le loro controparti on‑premise. Un quinto nodo avanzato, il graph editor, permette a un agente di modificare il proprio grafo.
| Nodo | Dove gira | Cosa offre all'agente | Persistenza |
|---|---|---|---|
| Connector | Container cloud, Node.js 22 | Le funzioni di tools.ts come tool tipizzati |
Repository git per nodo |
| Sandbox | Container cloud | Shell e file: exec, readFile, writeFile, editFile, listFiles |
Scope flow: effimera; scope node: condivisa e persistente |
| Machine at your site | Server Linux o PC Windows del cliente | Shell (sh o cmd) e file |
File system della macchina |
| Connector at your site | Node.js sulla macchina del cliente | Funzioni TypeScript vicino ai sistemi locali | Repository git della piattaforma |
Connector (connector)
Ogni funzione esportata da tools.ts diventa un tool con i suoi argomenti reali. È il modo per raggiungere un'API senza integrazione pronta, un calcolo proprio, una pulizia dati.
| Porta | Ruolo |
|---|---|
functions ("Your functions") |
Le funzioni come tool, più call e listFunctions |
developer ("Edit this workspace") |
Tool di sviluppo: exec, readFile, writeFile, editFile, listFiles, logs, commit, status, log |
tools ("Tools the code can call") |
Tool di altri nodi raggiungibili dal codice come targets.<node>.<tool>(…) |
agent ("Start a conversation") |
Un agente con cui il codice può conversare |
"Start from" sceglie un template per il workspace (example, microsoft365). La variante Microsoft 365 offre posta, calendario, OneDrive/SharePoint, Teams e persone come funzioni estendibili: con una connection per‑membro ogni chiamata avviene come la persona che parla con l'agente, con una connection applicativa agisce sull'intera azienda. "Secrets" dichiara per nome le credenziali che il codice può leggere. Reset o rimozione distruggono repository, working copy e container: il workspace viene ricreato dal template.
Una funzione nuova raggiunge gli agenti al reload del codice, senza ricostruire il grafo. Fino ad allora è raggiungibile con listFunctions + call. Il tipo avanzato Hello world è un connector minimo che risponde con un saluto: serve a testare un collegamento.
Sandbox (sandbox)
Una macchina Linux in container dove l'agente esegue comandi e tiene file: analisi con Python, conversioni di documenti, script di prova.
- Scope
flow(default): una macchina vuota per conversazione, eliminata dopo 30 minuti di inattività. Scopenode: una macchina condivisa da tutte le conversazioni, con directory di lavoro conservata tra i riavvii. - Container image:
python:3.12-slimper i dati,node:22-slimper JavaScript; default Debian minimale. L'agente può installare altro, ma conflowriparte da zero. execrestituisce exit code, stdout e stderr; un exit code non zero è un risultato normale. Output troppo lunghi vengono troncati: meglio redirigere su file e leggerlo a parti.- Richiede che l'ambiente abbia i container abilitati.
I dati importanti vanno in un file storage o in un database, non nella sandbox.
Machine at your site
Una macchina del cliente (server Linux o PC Windows) dove l'agente esegue comandi e legge o scrive file, accanto a sistemi senza API: un client di database legacy, cartelle condivise, un programma desktop. La macchina va prima registrata in Sites installando l'agente TeraBrain NX; poi si seleziona nel campo "Site". "Working directory" (avanzato) indica dove partono i comandi. Se la macchina è offline il nodo si costruisce comunque e ogni comando risponde che è offline. I comandi girano con i diritti con cui l'agente del sito è stato installato: mai a un agente pubblico.
Connector at your site
Un connector che gira su una macchina del cliente invece che in cloud: funzioni TypeScript vicino a un ERP in rete locale, un database senza indirizzo pubblico, una cartella condivisa. Node.js gira sulla macchina; il codice resta nel repository della piattaforma. Stesse porte del connector. Offline, si costruisce comunque e si riallinea da solo alla riconnessione. Se il codice non ha bisogno di nulla di locale, un connector cloud è più semplice.
Graph editor (avanzato)
La porta graph ("Edit this graph") dà a un agente i tool per leggere il proprio grafo, aggiungere e collegare nodi, cambiare campi, ricostruire e tornare a una versione precedente. Agisce solo sul grafo in cui vive. Ogni modifica è una nuova versione; i tool dell'agente stesso si aggiornano al turno successivo. Rimuovere un nodo con dati chiede conferma.
08Integrazioni MCP in ingresso
TeraBrain NX usa MCP in entrambe le direzioni. Il nodo MCP server (§5) espone il grafo all'esterno; i due nodi qui sotto portano dentro il grafo i tool di server MCP di terzi, come se fossero tool nativi. Entrambi hanno una sola porta, tools, da collegare alla porta tools degli agenti.
| Remote MCP server | Hosted MCP server | |
|---|---|---|
| Per server | pubblicati sul web (GitHub, Linear, Notion, un altro grafo TeraBrain NX) | distribuiti come comando (npx …, uvx …) |
| Dove gira | presso il fornitore | in un container dedicato della piattaforma |
| Configurazione | Server URL |
command come array, variabili d'ambiente |
| Credenziali | nessuna, bearer token o OAuth | variabili d'ambiente: valori o secret dell'organizzazione |
| Credenziali per‑membro | sì (userSecretRef o OAuth per membro) |
no: un processo per tutti |
| Variante pronta | — | Playwright browser |
Remote MCP server
L'autenticazione può essere assente, un bearer token (valore, secret dell'organizzazione {"secretRef": …}, secret personale {"userSecretRef": …} o connection {"connection": …}), oppure OAuth, collegato una volta dall'admin per tutta l'organizzazione o da ogni membro dal proprio profilo.
I tool vengono elencati alla build. Se il server non è raggiungibile o nessuno si è ancora collegato, il nodo si costruisce comunque con un tool generico e una nota; dopo il collegamento si ricostruisce per ottenere i tool reali. La description del nodo dà il nome ai tool letti dall'agente.
Un token personale su un agente che lavora senza nessuno collegato (mailbox, task schedulato) non funziona: non c'è un utente di cui usare il token.
Hosted MCP server
Esegue il programma del server nel proprio container, per esempio ["npx", "-y", "pkg@latest"]. Il primo avvio scarica il server e può richiedere minuti; se non parte, il nodo si costruisce con una nota e un tool generico, e i log ne spiegano il motivo.
- L'immagine di default contiene Node.js: un server Python (
uvx) richiede un'immagine con Python. - Un browser richiede un'immagine con i browser installati e più memoria: la variante Playwright browser imposta entrambe e dà agli agenti un browser pilotabile (apri pagina, clicca, scrivi, leggi, screenshot) senza chiavi né account.
- Il processo è unico per tutti: le credenziali sono sempre dell'organizzazione, mai di un membro.
09Telefonia
La telefonia è un piccolo centralino SIP dentro il grafo. Una chiamata entra dalla linea, attraversa nodi di instradamento (orari, routing per numero, menu a tasti) e arriva a un nodo voice, che la trasforma in una conversazione con un agente, oppure a un interno per una persona reale. Una chiamata non va mai direttamente a un agente.
| Nodo | Porte | Funzione |
|---|---|---|
| Phone line | inbound, outbound (source); calls (tool "Place a call") |
Account SIP presso il provider o centralino proprio |
| Phone extension | calls (sink e source), noAnswer |
Interno per telefono fisso, softphone o browser |
| Call routing | in + route dichiarate |
Instrada per numero chiamato (to) e chiamante (from) |
| Opening hours | in, open, closed |
Instrada in base a giorni, orari e festività |
| Phone menu | in + route per tasto |
IVR "premi 1 per…" con messaggio sintetizzato |
Phone line
Si configurano host SIP del provider, utente e password (meglio come secret). Il pannello del nodo indica se la linea è registrata; una password errata non fa fallire la build, lascia la linea non registrata. Più numeri sullo stesso account = più voci in ingresso, ognuna con i suoi numeri. I chiamanti con numero presente nel profilo di un membro vengono riconosciuti. "Record every call" è tra i campi avanzati.
La porta tool calls permette a un agente di telefonare: la chiamata è poi condotta dall'agente dietro outbound, attraverso un nodo voice, sulla base del brief scritto dal primo agente. Limitare sempre i numeri con allow (es. ["+39*"]).
Phone extension
Un numero interno unico nel grafo. Senza password impostata ne viene generata una, sufficiente per il telefono nel browser ("Open phone" nel pannello, con "Usable from the browser"); per un telefono fisso o un'app si imposta una password, meglio come secret. "Whose phone this is" attribuisce le chiamate a un membro. Se nessuno risponde (25 s di default) la chiamata va su noAnswer, per esempio a un nodo voice che prende un messaggio; se scollegata, si chiude. Due interni non si chiamano direttamente: il numero composto è instradato da un nodo Call routing. Per trasferire un chiamante su un interno, il numero va nella directory del nodo voice.
Call routing
Le regole si valutano in ordine e vince la prima che corrisponde. Ogni regola guarda to, from o entrambi con pattern come +3902*; una regola senza condizioni prende tutto. Le route in uscita vanno dichiarate nel nodo (una per destinazione, con id breve come sales, support); una regola la cui route non è collegata viene saltata. "Where unmatched calls go" nomina la route di default; senza, la chiamata viene chiusa. I pattern vanno scritti con il prefisso internazionale se la linea riporta i numeri come +39…: il formato reale si vede in Calls.
Opening hours
Time zone IANA (es. Europe/Rome), fasce di giorni (mon…sun) e orari HH:MM, festività YYYY-MM-DD nei campi avanzati. Due fasce per la pausa pranzo. Una fascia a cavallo della mezzanotte non corrisponde mai: si scrivono due fasce, fino alle 24:00 e dalle 00:00. closed scollegato = chiamata chiusa senza messaggio.
Phone menu
Il messaggio è sintetizzato una volta dal TTS scelto e riutilizzato: va scritto per intero, opzioni comprese. Ogni tasto (0–9, *, #) nomina una route verso un nodo voice, un interno o un altro menu. Senza tasto o con un tasto non valido il messaggio si ripete (due volte di default), poi la chiamata va a "Where invalid keys go" o si chiude. Per richieste espresse a parole è meglio un nodo voice che lasci decidere all'agente.
10Sviluppo dei workspace TypeScript
Connector, web app e connector at your site contengono un workspace: un progetto Node.js 22 eseguito in container e, insieme, una working copy git il cui origin è il repository del nodo. Il file autorevole è teranext/README.md, rigenerato a ogni build con i target reali del nodo: va letto prima di toccare il codice.
Struttura e ciclo di vita
/workspace
├── tools.ts # funzioni esposte come tool
├── app.ts # solo web app: handler HTTP
├── public/ # solo web app: file statici
├── package.json, tsconfig.json
└── teranext/ # generato a ogni build, committato, da non modificare
├── README.md # documentazione del workspace
├── functions.ts # defineFunction
├── tools.ts # targets, secrets, users, organization, file helper
└── agents.ts # solo con porte agent collegate
- TypeScript gira direttamente con
tsx; gli import possono omettere l'estensione.npx tsc --noEmitesegue il type‑check. npm install <pkg>funziona (rete disponibile);node_modules/è ignorata e reinstallata dapackage.json. File oltre 8 MB non sono tracciati.- Ogni scrittura è salvata subito (snapshot dopo ogni modifica, ripristinato se il runtime viene ricreato), ma la history di
mainsi scrive solo concommitogit commit+git push origin main. - Dopo ogni modifica il runtime si ricarica da solo; errori di caricamento e crash compaiono in
logs. - "Sleep when unused": il container si ferma dopo un periodo di inattività e riparte alla prima chiamata o visita. Timer e loop si fermano con lui: il codice che deve girare sempre richiede l'impostazione always‑on.
Lavorare da IDE
Ogni workspace ha un repository clonabile, mostrato nella sezione Code con il pulsante "Clone in VS Code":
git clone https://<utente>@api.nx.terabrain.ai/admin/repo/<graphId>/<nodeId> <nodeId>
La password è quella della console o un token. Chi fa push da un clone aggiorna main; la working copy del container segue main mantenendo le modifiche non committate, salvo conflitti (il tool status segnala quando è indietro). La vista Code mostra working copy o main, history per file e cartella.
Esporre funzioni: tools.ts
import { z } from "zod";
import { defineFunction } from "./teranext/functions";
export const tools = {
greet: defineFunction({
description: "Greets someone by name.",
input: z.object({ name: z.string().describe("Who to greet") }),
output: z.object({ greeting: z.string() }),
handler: async ({ name }) => ({ greeting: `Hello, ${name}!` }),
}),
};
L'input è validato con Zod prima dell'handler; il risultato deve essere serializzabile in JSON. La description è ciò che l'agente legge. call e listFunctions sono nomi riservati. L'handler riceve un secondo argomento ctx con flowId (la conversazione) e userId (l'utente per cui avviene la chiamata).
Chiamare altri nodi: targets
I tool collegati alla porta tools del nodo sono disponibili in teranext/tools.ts come funzioni async tipizzate, indirizzate per nodo provider:
import { targets } from "./teranext/tools";
const rows = await targets.tasks_db.query(
{ sql: "SELECT id, title FROM tasks WHERE status = ?", params: ["open"] },
{ userId: ctx.userId },
);
targets.<node>.<tool>è la forma stabile. L'aliasimport { query } from "./teranext/tools"esiste solo finché il nome ha un unico provider; con un secondo provider diventa uno stub che fallisce il type‑check e lanciaToolError.- Ogni chiamata accetta
{ flowId, userId, onProgress }. Un errore del tool lanciaToolError. - Forme non tipizzate:
invokeTool(name, args, { target })restituisce ilToolResultgrezzo;invokeToolStream(name, args, options)è un async iterable di eventi di progresso che termina con{ kind: "result", result }. - Il commento su ogni target in
teranext/tools.tsriporta i privilegi della porta e, per un database, lo schema. Ciò che la porta non consente si fa tramite un'altra porta dello stesso nodo, mai aggirandolo nel codice.
File e risorse
Tutti i tool TeraBrain NX rispondono con la stessa forma: testo piccolo inline, il resto allegato alla conversazione come risorsa (resourceId).
import { fileResult, resourceInput } from "./teranext/tools";
handler: async ({ asResource, resourceId }, ctx) => {
const source = resourceId ? await resourceInput(ctx, resourceId) : undefined;
const data = render(source);
return fileResult(ctx, { name: "report.csv", mimeType: "text/csv", data, asResource });
}
fileResult restituisce inline fino a 64 KB di testo e allega il resto. asResource: true forza il riferimento. Conviene offrire asResource e resourceId come input opzionali di ogni funzione che produce o consuma file. Senza conversazione (ctx.flowId assente) non c'è dove allegare: la regola automatica degrada a ciò che sta inline, e un asResource esplicito lancia errore.
Secrets
Nessuna variabile d'ambiente né file: il codice chiede il valore quando serve, per nome dichiarato nel nodo.
import { secrets } from "./teranext/tools";
const token = await secrets.get("openaiToken"); // secret dell'organizzazione
const mine = await secrets.get("crmToken", { userId }); // secret per‑utente
secrets.getlanciaSecretNotAvailableError { name, scope, connectUrl }se il valore manca.secrets.list({ userId })indica quali secret sono dichiarati e se sono impostati, senza valori: utile per mostrare "collega il tuo account".secrets.set(name, value, { userId })esecrets.deletesalvano un token ottenuto dal codice stesso (solo per secret di organizzazione o utente).- La rotazione non richiede riavvii. Per librerie che pretendono una variabile d'ambiente:
process.env.X = await secrets.get("X")all'avvio.
Utenti e variabili
users.get, users.getByEmail, users.getByIdentity(provider, id), users.list() restituiscono membri con userId, email, name, identities, role, groups. Le variabili per utente (users.getVariable/setVariable/deleteVariable/listVariables) e per organizzazione (organization.getVariable/…) sono valori JSON condivisi da tutti i nodi dell'organizzazione: preferenze, cursori, memorie. Mai credenziali.
Variabili d'ambiente del runtime
| Variabile | Contenuto |
|---|---|
TERANEXT_BRIDGE_URL, TERANEXT_BRIDGE_TOKEN |
Usate da teranext/tools.ts; mai inviarle al browser |
TERANEXT_REPO_URL |
Repository del nodo (origin) |
TERANEXT_WORKDIR |
Directory del workspace |
TERANEXT_PUBLIC_URL |
Solo web app: URL pubblico |
TERANEXT_AUTH_URL |
Solo web app: pagine di login e logout |
11Web app con assistente
Una web app con una chat all'interno è il caso d'uso principale della piattaforma. Il turno dell'agente gira dentro TeraBrain NX; la pagina si limita a osservarlo. Per questo un reload a metà risposta o una risposta di un'ora non perdono nulla.
L'applicazione HTTP
L'app risponde su https://api.nx.terabrain.ai/graph/<graphId>/node/<nodeId>/app/ (o su un hostname dedicato). Un file in public/ che corrisponde al percorso è servito così com'è (index.html per le directory). Altrimenti risponde app.ts, che esporta di default una di queste forme:
- un handler fetch‑style
(request: Request) => Response | Promise<Response>; - un oggetto con metodo
fetch(es. un'app Hono); - un handler Node
(req, res) => void(Express funziona così com'è).
L'app è montata sotto un prefisso: l'handler vede percorsi relativi e i link nelle pagine devono essere relativi (./style.css, api/hello), mai assoluti. Il prefisso arriva nell'header X-Forwarded-Prefix. Solo HTTP request/response viene proxato: niente WebSocket, quindi lo streaming usa Server‑Sent Events.
Identità del visitatore
La piattaforma imposta questi header e rimuove quelli in ingresso, quindi non sono falsificabili:
| Header | Contenuto |
|---|---|
x-teranext-principal |
anonymous, user o operator |
x-teranext-user-id |
Id del visitatore |
x-teranext-email, x-teranext-name (URL‑encoded) |
Solo membri |
x-teranext-role, x-teranext-groups (separati da virgola) |
Solo membri |
Il userId si legge sempre dall'header, mai da ciò che invia il browser. Un'app riservata reindirizza il browser anonimo al login (TERANEXT_AUTH_URL). Il logout è un form POST a ${TERANEXT_AUTH_URL}logout con un campo next; la sessione è unica per il deployment, quindi esce da console e app insieme.
Parlare con gli agenti: teranext/agents.ts
Gli agenti collegati alle porte source del nodo sono client di conversazione (agents.<porta>). Il codice nomina la porta; quale agente risponde lo decide il cablaggio del grafo.
| Metodo | Scopo |
|---|---|
open({ key?, userId?, parentFlowId?, traces? }) |
Apre (o ritrova per key) una conversazione → { flowId, created } |
send(text, { flowId?, userId?, resourceIds?, mode?, timeoutSeconds? }) |
Invia e attende, oppure mode: "background" e ritorna subito. Un turno alla volta: il secondo è 409 |
events(flowId, { userId? }) |
Stream infinito: state, poi chunk, reply, trace, heartbeat |
cancel(flowId, { userId? }) |
Ferma il turno in corso |
stream(…) |
Eventi di questa chiamata fino a result: per funzioni che inoltrano il progresso |
list({ key?, userId?, parentFlowId?, limit?, cursor? }) |
Conversazioni con preview e lastMessageAt |
history(flowId, { userId?, limit?, cursor?, reverse? }) |
Messaggi, tool activity come trace, risorse, busy |
Il bridge risponde 403 per una conversazione che non appartiene al userId passato. Le conversazioni senza messaggi oltre il periodo di retention dei log (30 giorni di default) vengono eliminate: list non le mostra più e il flowId risponde 404.
Il pattern di chat corretto
La recipe "Web app with an assistant" e il README del workspace descrivono una chat completa con sette route:
| Route | Implementazione |
|---|---|
GET /api/conversations |
chat.list({ userId, limit: 50 }): la sidebar |
POST /api/conversations |
chat.open({ userId, traces: true }): pulsante New conversation, senza key |
GET /api/history |
chat.history(flowId, { userId }): il passato |
GET /api/events |
eventStreamResponse(chat.events(flowId, { userId })): il presente, in SSE |
POST /api/message |
uploadResource per ogni file (max 25 MB), poi chat.send(…, { mode: "background" }) e risposta 202 |
POST /api/cancel |
chat.cancel(flowId, { userId }): pulsante Stop |
GET /api/resource |
Controllo di proprietà via history, poi readResource(flowId, resourceId) con il MIME type |
Regole di UX che il README rende obbligatorie:
- Conversazioni per visitatore con lista e pulsante New: mai una conversazione infinita per persona, che farebbe crescere il contesto senza limite.
keyserve a legare una conversazione a una cosa (un ordine, un ticket), non a una persona. - Invio in background e risposta seguita sugli eventi; mai attendere la risposta nella richiesta di invio.
- Input disabilitato e pulsante Stop mentre
state.busyè vero. - Risposta in Markdown, renderizzata a ogni
chunkin una bolla perstreamIde sostituita dal contenuto definitivo alreply. Mai inserire il testo del modello ininnerHTMLsenza sanificarlo (per esempio marked + DOMPurify). - File in entrambe le direzioni: chip nella bolla dell'utente; per le risposte,
<img>,<audio>o link di download serviti dalla route/api/resource. Per file grandiresourceLink(flowId, resourceId)fornisce un URL pubblico con scadenza, se l'ambiente li abilita. - Traces (
traces: true) mostrano cosa sta facendo l'agente: meglio di uno spinner. - Visitatore anonimo: nessun
userId, quindi nientelist; la pagina conserva i propriflowIdinlocalStorage. IlflowIdè casuale e non indovinabile: è l'unica protezione.
Una funzione può passare un file ricevuto a un agente senza leggerne i byte: agents.agent.send(task, { parentFlowId: ctx.flowId, userId: ctx.userId, resourceIds: [input.resourceId] }).
12Builder e assistenti esterni
I grafi si possono costruire e sviluppare conversando: con il Builder integrato (sezione Build) o con un assistente esterno collegato dal profilo. Entrambi lavorano con i diritti della persona, in una organizzazione, e ogni modifica diventa una nuova versione del grafo registrata a suo nome; nel log Changes compare come "via Builder" o "via MCP".
Collegare un assistente esterno
In Profile → "Connect an assistant" si sceglie l'organizzazione, si dà un nome al client ("Claude Desktop sul mio laptop") e si crea un token. Client supportati: Claude Desktop, Cowork, Claude Code, Codex. Ogni assistente ha il proprio token, revocabile in qualsiasi momento; la creazione è tracciata come access-token.create.
Non va confuso con il nodo MCP server (§5): quello espone i tool e un agente di un singolo grafo, questo espone la piattaforma per costruire grafi.
Cosa legge il Builder
La pagina Docs → "What the Builder is told" pubblica il primer che il Builder e gli assistenti collegati leggono prima di costruire; le pagine dei tipi di nodo e delle recipe sono lo stesso testo servito dal tool catalog. Il ciclo di lavoro prescritto:
- Capire cosa c'è:
organization(secret e connection per nome, model profile, sites, servizi),recipes,listGraphs,describeGraph. - Leggere prima di scrivere:
catalog {type}per ogni tipo usato, con guida, campi (JSON Schema), id delle porte ed esempi. Mai indovinare un nome di campo. - Partire da una recipe quando calza:
createGraph {name, recipe}. - Costruire con
applyGraph, una chiamata per pezzo coerente (un canale, il suo agente, i suoi tool), condryRun: truein caso di dubbio.updateNode,connecte simili servono per le correzioni. - Verificare con
checkGraphdopo ogni modifica. - In caso di errore:
status, poilogs(solo admin), correggere la causa.rollbackè la via d'uscita da una build rotta.
Per il codice: workspace {graph, node} per primo, sempre, perché restituisce il README; poi readFile, editFile (sostituzione esatta, preferita a writeFile), exec (es. npx tsc --noEmit), appLogs, nodeTools e callNodeTool per provare le funzioni, e commit dopo ogni modifica coerente.
Protezioni
- Nessun tool dell'assistente cancella un grafo.
- Rimuovere un nodo con dati, cambiarne il tipo o fare rollback oltre il punto in cui è stato aggiunto viene rifiutato senza
confirm: true; il rifiuto dice cosa andrebbe perso. L'assistente deve chiedere all'utente e confermare solo dopo un sì esplicito. - I secret non si chiedono, non si scrivono e non si ripetono: il nodo li referenzia per nome e l'assistente indica quale nome impostare in console.
- Agli agenti rivolti al pubblico non si danno accesso completo, cancellazione o modifica del codice.
Il Builder risponde nella lingua dell'utente, senza gergo né JSON, dice cosa ha costruito e cosa resta da fare all'utente (impostare un secret, creare un bot, registrare un numero). Nella vista Build il grafo si disegna in tempo reale e ogni nodo diventa verde quando gira.
13Modelli LLM
I modelli si configurano per organizzazione in Organization → Settings, in due livelli: AI Providers (gli endpoint) e Model Profiles (configurazioni nominate che gli agenti referenziano). Qualunque endpoint compatibile con le API OpenAI può essere un provider, quindi anche un LLM privato o on‑premise esposto con un'interfaccia compatibile.
AI Providers
| Campo | Descrizione |
|---|---|
Provider Id |
Nome con cui i model profile si riferiscono al provider (es. openrouter, openai) |
Api Type |
Protocollo: completions (OpenAI Chat Completions) o responses (OpenAI Responses) |
Base Url |
URL base dell'API, es. https://api.openai.com/v1 |
Api Key |
Inviata come bearer token; mascherata in console |
Model Profiles
| Campo | Descrizione |
|---|---|
Profile Id |
Nome usato dagli agenti nel campo Model |
Provider Id |
Uno dei provider dell'organizzazione |
Model |
Nome del modello come lo attende il provider |
Settings |
Parametri di chiamata; il loro apiType deve coincidere con quello del provider |
Parametri disponibili secondo il protocollo:
- completions:
Temperature,Max Tokens,Reasoning Effort(low, medium, high; inviato come blocco reasoning in stile OpenRouter dove supportato). - responses:
Max Output Tokens(ragionamento incluso),Reasoning Effort(minimal, low, medium, high),Web Search(abilita il toolweb_searchnativo della Responses API).
Default e scelta per agente
"Default model" indica il profilo usato dagli agenti che non ne nominano uno (se non impostato, il primo profilo). Ogni agente può sceglierne un altro: in un team di agenti conviene un modello piccolo e veloce in prima linea e uno più capace per il lavoro difficile. Il campo Model dell'agente mostra sempre quale sia il default corrente dell'organizzazione.
Il Timezone dell'organizzazione (IANA, Europe/Rome se non impostato) è il fuso degli orologi dell'organizzazione e il default dei task schedulati che non ne indicano uno.
14Sicurezza e governance
La sicurezza di un grafo si regge su quattro leve: i ruoli delle persone, le credenziali referenziate per nome e mai esposte, il minimo privilegio sulle porte, e il controllo d'accesso di ogni canale. Tutte le modifiche restano tracciate (§15).
Organizzazioni e ruoli
Una persona può appartenere a più organizzazioni e cambiarle dal selettore in console. In Organization → Members ogni membro ha un ruolo, gruppi e un'eventuale identità Telegram collegata.
| Ruolo | Permessi |
|---|---|
user |
Conversa con gli agenti consentiti e apre le app dell'organizzazione |
fullmember |
In più costruisce: grafi, codice, dati |
admin |
In più gestisce impostazioni, membri, secret e connection dell'organizzazione |
I gruppi servono a restringere agenti ("Who may talk to it"), web app, bot, mailbox e librerie di skill a un sottoinsieme di membri.
Secrets
I valori sensibili non transitano mai verso il browser: scriverne uno lo sostituisce, nessuno può rileggerlo. Un nodo li referenzia così:
| Riferimento | Significato |
|---|---|
{"secretRef": "NAME"} |
Secret dell'organizzazione, impostato da un admin in Organization → Secrets |
{"userSecretRef": "NAME"} |
Secret personale di ogni membro, impostato dal proprio profilo |
{"connection": "name"} |
Token OAuth di una connection, rinnovato dalla piattaforma |
La tabella Secrets mostra per ogni nome lo stato (set, connected (OAuth)), chi l'ha impostato e quale nodo lo richiede.
Connections (OAuth)
Una connection è un'applicazione OAuth registrata una volta presso un provider (Microsoft 365, Google, un CRM). Scope organization: la collega un admin; scope user: la collega ogni membro dal proprio profilo, e il token finisce in un suo secret. Il redirect URI da registrare presso il provider è unico per tutto il deployment: https://api.nx.terabrain.ai/auth/connect/callback.
Identità e SSO
Organization → Identity abilita il login tramite directory aziendale; oggi è implementato Microsoft Entra ID. Chi ha un account nel tenant e un'email di uno dei domini configurati entra con un pulsante, senza password TeraBrain NX.
- Si basa su una connection esistente (issuer, client id, client secret); redirect URI di login:
https://api.nx.terabrain.ai/auth/login/callback. Tenant: iltiddel token viene verificato a ogni login.Auto Joincon un ruolo: la persona diventa membro al primo accesso.Group Mappings: gruppi Entra → ruolo ed etichette, con il claim opzionalegroupsattivo sull'applicazione (oltre circa 200 gruppi il token non li riporta).Sync: lettura periodica della directory (default 60 minuti) in modalità applicativa conGroupMember.Read.AlleUser.Read.All;Remove Leaversrimuove chi non è più nei gruppi mappati, mai membri aggiunti a mano né l'ultimo admin.
Variabili
Organization → Variables e Profile → Variables contengono stato di runtime non segreto (valori JSON), leggibile e scrivibile dai nodi. Le credenziali vanno sempre nei secret.
Minimo privilegio: checklist
- Agenti pubblici: niente
adminsui database, nienterwsui file storage, nientedeveloper, niente sandbox o macchine on‑premise. allowsulle porte che inviano all'esterno: destinatari email, numeri chiamabili, transfer.- Web app con dati aziendali: accesso
organizationogroup, maipublic. - Indirizzo del nodo MCP server trattato come una password; ruotarlo cambiando
apiKey. - Link pubblici (
shareFile,linkResource) solo dove servono, con scadenza breve. - Credenziali mai nel codice: dichiarate in "Secrets" del nodo e lette con
secrets.get.
15Osservabilità
Ogni conversazione, chiamata di tool e modifica del grafo è registrata e consultabile dalla sezione Logs, con export CSV e JSONL. In fase di sviluppo si aggiungono Checks e Try it nell'editor e il tool logs dei workspace.
Logs
| Vista | Cosa mostra | Filtri |
|---|---|---|
| Flows | Una riga per conversazione: quando, origine, persona, primo messaggio, numero di tool call, errori, durata | Grafo, periodo, origine, nodo, persona, "With errors" |
| Tool calls | Una riga per chiamata: tool, provider, chiamante (e conversazione), persona, esito, durata | Grafo, periodo, tool, provider, persona, connection, esito |
| Graph | Il grafo con le linee pesate per numero di chiamate (scala log) e colorate per tasso d'errore | Grafo, periodo |
| Changes | Audit: chi (anche "via Builder" o "via MCP"), azione (graph.create, graph.update, node.rebuild, access-token.create…), oggetto, dettagli, esito, Diff |
Periodo, grafo, persona, azione |
| Person | Tutto ciò che un membro ha fatto o causato | Membro, periodo |
Le origini filtrabili sono Console chat or app, Telegram, Email, Phone, Scheduled task, Delegated, Request, Operator, System. I periodi vanno da un'ora a 30 giorni o personalizzati.
Tracing di una conversazione
Aprendo un flow si ottiene la sua traccia completa, con tre viste:
- Waterfall: ogni agente coinvolto (anche le conversazioni figlie da delega o subtask) con le sue tool call nel tempo e la durata di ciascuna.
- Causal tree: chi ha causato cosa.
- Replay: la conversazione che attraversa il grafo, passo per passo.
Il pannello di dettaglio riporta origine, persona, chi ha aperto e chi ha risposto (nodo e porta), inizio e durata, numero di tool call ed errori, ultimo errore, e i token dichiarati dal modello in ingresso e in uscita. Sotto c'è la trascrizione con ogni calling / result of in ordine.
La vista Graph segnala anche le chiamate tra nodi che nessuna linea di tool collega più (per esempio dopo una modifica), utile per trovare dipendenze rimaste nel codice.
In fase di sviluppo
- Checks nell'editor: problemi che impediscono al grafo di girare e avvisi "Worth knowing" con correzioni proposte.
- Try it: chat di prova con qualunque agente del grafo, con tool activity.
- Tool activity nelle chat della console: ogni chiamata e risultato inline.
logs,statuselogsulla portadeveloperdei workspace: output del runtime, errori di caricamento, crash, stato git.- Il registro delle chiamate telefoniche (Calls) e delle esecuzioni schedulate (Scheduled tasks).
La retention dei log dipende dall'organizzazione (30 giorni se non diversamente configurato); le conversazioni inattive oltre quel periodo vengono eliminate.
16Recipes
Una recipe è un grafo di partenza già cablato: si usa da Graphs → New graph, si inserisce in un grafo esistente dai Patterns dell'editor, oppure si chiede al Builder (createGraph {name, recipe}).
| Recipe | Nodi | Da compilare | Nota tecnica |
|---|---|---|---|
| Telegram assistant | telegram, agente |
Token del bot (o nome di un secret) | Di default risponde a chiunque trovi il bot |
| Web app with an assistant | webapp, agente |
Nome dell'app, riga descrittiva | Accesso di default organization; le funzioni dell'app sono i tool dell'assistente |
| Mailbox assistant | mailbox hosted, agente | Parte prima della @ |
Lavora senza nessuno collegato: solo risorse dell'organizzazione o di un account fissato |
| Phone receptionist | linea SIP, orari, voice, agente |
Host SIP, account, password, chiavi ElevenLabs | Orari iniziali lun–ven 9–13 e 14–18, Europe/Rome; closed scollegato |
| Agent with your code | connector, database, agente | Descrizione del codice e del database | L'agente ha rw sul database (non crea tabelle); "Edit this workspace" lasciato scollegato di proposito |
| Team of agents | tre agenti: Front desk, Specialist, Colleague | Ruolo di specialist e colleague | Specialist via delegate, Colleague via handoff; per un terzo collega si copia un link |
Dopo la creazione, ogni recipe richiede gli stessi passi: scegliere il modello (o lasciare il default), riscrivere le istruzioni dell'agente, salvare e costruire, poi collegare i tool o il canale che mancano.
17Best practice e riferimento rapido
Progettazione
- Un agente, un mestiere. Istruzioni specifiche, pochi tool coerenti; per il resto delega (
delegate) o passa la conversazione (handoff). - Le descrizioni sono prompt.
descriptiondi database, storage, connector, portedelegate/handoffe skill vengono lette dal modello: dicono cosa c'è e quando usarlo. - Le procedure lunghe vanno in skill, non nelle istruzioni: si caricano solo quando servono e si riutilizzano tra agenti.
- Nomi leggibili. Grafo per scopo ("Customer support"), nodi brevi e parlanti (
support-agent,orders-db). - Dati fuori dalla sandbox. Lo stato durevole va in database o file storage.
- Pensare all'esecuzione non presidiata. Mailbox e scheduler non hanno utente collegato: niente token personali.
Sviluppo
- Leggere
teranext/README.mdprima di ogni sessione di sviluppo e dopo ogni build. - Indirizzare i tool con
targets.<node>.<tool>, mai con l'alias quando i provider possono crescere. - Passare sempre
ctx.userIdai tool e agli agenti chiamati dal codice. npx tsc --noEmitdopo ogni modifica,logsquando qualcosa non risponde,commitcon un messaggio che dica cosa e perché.- Nelle web app, leggere l'utente dagli header e seguire le sette route del pattern di chat.
Errori tipici
| Sintomo | Causa probabile |
|---|---|
| Il bot Telegram non riceve messaggi | Stesso token su un altro nodo o grafo costruito dopo |
| La linea SIP non riceve chiamate | Password errata (linea non registrata) o stesso account su due linee |
| L'agente non riesce a creare tabelle | Ha solo rw: serve admin o uno sviluppatore |
| L'agente al telefono non trasferisce | control non collegato o directory vuota |
| Una regola di routing non scatta mai | Pattern senza prefisso internazionale, o route non collegata |
| Gli orari notturni non funzionano | Fascia a cavallo della mezzanotte: usare due fasce |
| Hosted MCP non parte | Server Python su immagine Node, o browser senza memoria sufficiente |
| I file della sandbox spariscono | Scope flow: la macchina è per conversazione |
| Un task schedulato fallisce sull'account | Nessuno è collegato all'ora del task: usare risorse dell'organizzazione |
Errore 409 da send |
Un turno è già in corso sulla conversazione |
Riferimento rapido delle porte
| Tipo | Provides tools | Uses tools | Starts conversations | Answers |
|---|---|---|---|---|
| Agent | developer |
tools |
delegate, handoff |
sink |
| Web app | functions, developer |
tools |
agent |
— |
| Connector / at your site | functions, developer |
tools |
agent |
— |
| Telegram bot | — | — | source |
— |
| Mailbox | mail |
— | inbound |
— |
| MCP server | — | tools |
agent |
— |
| Voice | control |
— | agent |
calls |
| Scheduler | schedule |
tools |
agent |
— |
| MySQL database | admin, rw (+ ro) |
— | — | — |
| Skill library | rw, ro |
— | — | — |
| File storage | rw, ro |
— | — | — |
| Sandbox | sandbox |
— | — | — |
| Machine at your site | site |
— | — | — |
| Graph editor | graph |
— | — | — |
| Remote / Hosted MCP server | tools |
— | — | — |
| Phone line | calls |
— | inbound, outbound |
— |
| Phone extension | — | — | calls, noAnswer |
calls |
| Call routing | — | — | route dichiarate | in |
| Opening hours | — | — | open, closed |
in |
| Phone menu | — | — | route per tasto | in |