Memória de aprendizados
Memória de longo prazo para agentes de IA: salve o que aprendeu em cada projeto e recupere antes da próxima tarefa.
Os agentes gravam armadilhas, decisões, convenções e receitas aprendidas em cada projeto e, na próxima tarefa, recuperam só o que é relevante. Funciona sobre uma base de conhecimento criada automaticamente, com deduplicação e busca semântica.
- Base path
/v1/tools/learnings- Escopos
tools:learnings:readtools:learnings:writetools:manage
Como funciona
Um aprendizado é um texto curto com um kind, ligado a um project:
kind | Para guardar |
|---|---|
pitfall | Armadilhas e erros que não devem se repetir. |
decision | Decisões tomadas e o motivo. |
convention | Convenções do projeto. |
howto | Como fazer algo (rodar, publicar, depurar). |
other | O que não cabe nos outros. |
Os aprendizados ficam numa base de conhecimento chamada agent-learnings, criada sozinha na primeira gravação. O recall faz uma busca semântica pela tarefa e devolve só os itens do project pedido, com a score de cada um.
Também está disponível no MCP como learning_save, learning_recall e learning_forget (toolset learnings).
| Operação | Rota |
|---|---|
| Salvar aprendizado | POST/ |
| Recuperar aprendizados | POST/recall |
| Esquecer aprendizado | DELETE/{id} |
Duplicados e ingestão assíncrona
- Deduplicação: o
savecompara por hash e por similaridade semântica. Se já existe um aprendizado igual ou parecido, nada novo é gravado e a resposta trazduplicate_ofcom o id do existente. - Ingestão assíncrona: o texto é indexado em segundo plano. Um
recalllogo depois de umsavepode ainda não trazer o item; tente de novo em alguns segundos.
Custos
A cobrança é a da base de conhecimento: o save como a ingestão (por trecho), o recall como a busca (franquia diária + blocos) e o armazenamento por dia. Esquecer é grátis. A memória segue as mesmas regras de liberação da base de conhecimento (rag.disabled e demais erros rag.*).
Endpoints
Salvar aprendizado
/v1/tools/learnings- Custo
- Cobrado como a ingestão da base de conhecimento (por trecho)
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:learnings:writetools:manage
project, kind e text são obrigatórios; source é opcional e diz de onde veio. A resposta traz o id do aprendizado ou, se for repetido, duplicate_of.
curl -sS -X POST 'https://api.respawntech.dev/v1/tools/learnings' \
-H "X-API-Token: $RESPAWN_API_TOKEN" \
-H 'Content-Type: application/json' \
-d '{ "project": "respawn-tech-docs", "kind": "pitfall", "text": "O check:backend lê ../respawn-tech-backend; rode só com o backend já junto.", "source": "conversa de 06/10" }'const response = await fetch('https://api.respawntech.dev/v1/tools/learnings', {
method: 'POST',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
'Content-Type': 'application/json',
},
body: JSON.stringify({ "project": "respawn-tech-docs", "kind": "pitfall", "text": "O check:backend lê ../respawn-tech-backend; rode só com o backend já junto.", "source": "conversa de 06/10" }),
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.post(
"https://api.respawntech.dev/v1/tools/learnings",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
json={ "project": "respawn-tech-docs", "kind": "pitfall", "text": "O check:backend lê ../respawn-tech-backend; rode só com o backend já junto.", "source": "conversa de 06/10" },
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/learnings');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => <<<'JSON'
{ "project": "respawn-tech-docs", "kind": "pitfall", "text": "O check:backend lê ../respawn-tech-backend; rode só com o backend já junto.", "source": "conversa de 06/10" }
JSON,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"strings"
"time"
)
func main() {
req, err := http.NewRequest("POST", "https://api.respawntech.dev/v1/tools/learnings", strings.NewReader(`{ "project": "respawn-tech-docs", "kind": "pitfall", "text": "O check:backend lê ../respawn-tech-backend; rode só com o backend já junto.", "source": "conversa de 06/10" }`))
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 201
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000"
}
}Recuperar aprendizados
/v1/tools/learnings/recall- Custo
- Cobrado como a busca da base de conhecimento (franquia diária + blocos)
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:learnings:readtools:manage
project e task são obrigatórios; top_k limita quantos itens voltam. Cada item traz id, kind, text, source e score. Lembre que a ingestão é assíncrona: um item recém-salvo pode ainda não aparecer.
curl -sS -X POST 'https://api.respawntech.dev/v1/tools/learnings/recall' \
-H "X-API-Token: $RESPAWN_API_TOKEN" \
-H 'Content-Type: application/json' \
-d '{ "project": "respawn-tech-docs", "task": "rodar os checks antes de abrir o PR", "top_k": 5 }'const response = await fetch('https://api.respawntech.dev/v1/tools/learnings/recall', {
method: 'POST',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
'Content-Type': 'application/json',
},
body: JSON.stringify({ "project": "respawn-tech-docs", "task": "rodar os checks antes de abrir o PR", "top_k": 5 }),
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.post(
"https://api.respawntech.dev/v1/tools/learnings/recall",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
json={ "project": "respawn-tech-docs", "task": "rodar os checks antes de abrir o PR", "top_k": 5 },
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/learnings/recall');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => <<<'JSON'
{ "project": "respawn-tech-docs", "task": "rodar os checks antes de abrir o PR", "top_k": 5 }
JSON,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"strings"
"time"
)
func main() {
req, err := http.NewRequest("POST", "https://api.respawntech.dev/v1/tools/learnings/recall", strings.NewReader(`{ "project": "respawn-tech-docs", "task": "rodar os checks antes de abrir o PR", "top_k": 5 }`))
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 200
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"items": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"kind": "pitfall",
"text": "O check:backend lê ../respawn-tech-backend; rode só com o backend já junto.",
"source": "conversa de 06/10",
"score": 0.82
}
]
}
}Esquecer aprendizado
/v1/tools/learnings/{id}- Custo
- Grátis
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:learnings:writetools:manage
curl -sS -X DELETE 'https://api.respawntech.dev/v1/tools/learnings/550e8400-e29b-41d4-a716-446655440000' \
-H "X-API-Token: $RESPAWN_API_TOKEN"const response = await fetch('https://api.respawntech.dev/v1/tools/learnings/550e8400-e29b-41d4-a716-446655440000', {
method: 'DELETE',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
},
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.delete(
"https://api.respawntech.dev/v1/tools/learnings/550e8400-e29b-41d4-a716-446655440000",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/learnings/550e8400-e29b-41d4-a716-446655440000');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"time"
)
func main() {
req, err := http.NewRequest("DELETE", "https://api.respawntech.dev/v1/tools/learnings/550e8400-e29b-41d4-a716-446655440000", nil)
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 200
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"deleted": true
}
}Atualizado em
Base de conhecimento
Busca híbrida (semântica + palavras-chave) nos seus documentos, com rerank e feedback de relevância, para RAG e assistentes de IA.
Áudio
Transcrição, voz sintética, efeitos e músicas, análise, conversão, resumo, tradução e revoice de áudio, por REST ou MCP, com jobs assíncronos e preço por minuto.