Layven
Unidade compartilhada para seus agentes e colegas de equipe.
Documentação
Servidor MCP Layven
Layven é um drive compartilhado que seus agentes montam via MCP. Cada escrita é versionada, cada ação é atribuída ao agente que a realizou, e qualquer coisa pode ser revertida.
Um bloco de configuração, sem alterações no código do agente. Hospedado em https://api.layven.io/mcp.
Documenta o servidor MCP Layven 1.0.2.
Início rápido
claude mcp add --transport http layven https://api.layven.io/mcp --header "Authorization: Bearer agd_your_agent_token"
- Obtenha um token em layven.io: abra o console, vá em Agents, crie um. O segredo é mostrado uma única vez.
- Reinicie seu cliente.
- Pergunte ao seu agente: "liste meus workspaces Layven".
O ponto do produto aparece na segunda conexão. Crie um segundo token, conecte uma ferramenta diferente com ele, e faça essa ferramenta ler o arquivo que a primeira acabou de escrever. Ambos os agentes veem o mesmo drive, e o feed de atividade diz quem fez o quê. Passo a passo: examples/two-agent-handoff.md.
Conecte seu cliente
Claude Code
claude mcp add --transport http layven https://api.layven.io/mcp --header "Authorization: Bearer agd_your_agent_token"
Conector personalizado Claude.ai
Cole https://api.layven.io/mcp e autentique com OAuth. Essa interface não tem campo de cabeçalho personalizado, e é por isso que o OAuth existe.
ChatGPT
Igual ao Claude.ai: cole https://api.layven.io/mcp e autentique com OAuth.
Cursor (~/.cursor/mcp.json)
{
"mcpServers": {
"layven": {
"url": "https://api.layven.io/mcp",
"headers": {
"Authorization": "Bearer agd_your_agent_token"
}
}
}
}
Codex (~/.codex/config.toml)
[mcp_servers.layven]
url = "https://api.layven.io/mcp"
http_headers = { "Authorization" = "Bearer agd_your_agent_token" }
Gemini (~/.gemini/settings.json)
Mesmo JSON do Cursor, mas a chave é httpUrl em vez de url, porque o Gemini lê url como um endpoint SSE.
{
"mcpServers": {
"layven": {
"httpUrl": "https://api.layven.io/mcp",
"headers": {
"Authorization": "Bearer agd_your_agent_token"
}
}
}
}
JSON MCP genérico
{
"mcpServers": {
"layven": {
"url": "https://api.layven.io/mcp",
"headers": {
"Authorization": "Bearer agd_your_agent_token"
}
}
}
}
Autenticação
Existem duas formas de acesso, e ambas resolvem para o mesmo registro de token, então permissões, revogação e trilha de auditoria são idênticas de qualquer forma.
Token bearer estático. Envie Authorization: Bearer agd_... em cada requisição. Crie-o no console; o segredo é mostrado uma única vez.
OAuth 2.1, para clientes cuja interface não tem campo de cabeçalho personalizado:
| Servidor de autorização | https://api.layven.io |
| Metadados do recurso protegido | https://api.layven.io/.well-known/oauth-protected-resource/mcp |
| Recurso | https://api.layven.io/mcp |
| Registro dinâmico de cliente | Suportado |
| Expiração do segredo do cliente | Não expira |
O consentimento gera um token comum, que você pode ver e revogar no console como qualquer outro.
Transporte
POST https://api.layven.io/mcp, HTTP Streamable, sem estado.- Cada POST é totalmente independente. Sem id de sessão, sem retomada de sessão, sem endpoint SSE separado, sem stdio.
- GET e DELETE retornam HTTP 405 com exatamente este corpo:
{"jsonrpc":"2.0","error":{"code":-32000,"message":"Method not allowed (stateless)"},"id":null} - Cabeçalhos de requisição obrigatórios:
Content-Type: application/jsoneAccept: application/json, text/event-stream. Ambos os tipos de mídia devem estar presentes emAcceptou o servidor retorna 406. - Respostas voltam como
Content-Type: text/event-stream. MCP-Protocol-Versioné opcional. Se presente, deve ser um de2025-11-25,2025-06-18,2025-03-26,2024-11-05,2024-10-07, caso contrário o servidor retorna HTTP 400.- Capacidades: apenas
tools. Sem recursos, sem prompts. - Identidade do servidor em
initialize: nomeLayven, versão1.0.2, sitehttps://layven.io.
Ferramentas
Toda ferramenta aceita um workspace opcional, o slug do workspace. Um token com permissão para exatamente um workspace pode omiti-lo. list sem workspace se espalha por todos os workspaces que o token pode alcançar.
| Ferramenta | Acesso | Faz | Argumentos-chave |
|---|---|---|---|
list | ro | Lista uma pasta, ou encontra arquivos por substring do caminho | path, recursive, q, limit |
read | ro | Lê um arquivo na versão atual ou em uma versão anterior | path, version |
grep | ro | Pesquisa o conteúdo de arquivos com um padrão RE2 | pattern, prefix, context_lines, max_matches |
history | ro | Lista as versões de um arquivo, da mais nova para a mais antiga | path, limit, cursor |
activity | ro | Lista o que mudou e qual agente mudou | since, path_prefix, limit |
write | rw | Cria ou substitui um arquivo com conteúdo inline | path, content, encoding, expected_version |
edit | rw | Aplica substituições de string em um arquivo de texto existente | path, edits, expected_version |
move | rw | Move ou renomeia um arquivo | from, to, overwrite |
delete | rw | Marca um arquivo como excluído, recuperável com restore | path, expected_version |
restore | rw | Restaura um arquivo para uma versão, ou uma pasta para um timestamp | path + to_version, ou prefix + at |
lock | rw | Obtém um bloqueio consultivo de 5 minutos em um caminho | path |
unlock | rw | Libera um bloqueio que este token detém | path |
request_upload | rw | Inicia um upload de arquivo grande, retorna uma URL PUT pré-assinada | path, size, expected_version |
finalize_upload | rw | Confirma um arquivo enviado como uma nova versão | upload_id |
Apenas delete é anotada como destrutiva, e ela escreve uma versão de tombstone que restore traz de volta. write, delete, lock e unlock são anotadas como idempotentes; edit, move, restore, request_upload e finalize_upload não são. Nenhuma ferramenta alcança fora do Layven.
NOT_FOUND (workspace não resolvível), PERMISSION_DENIED, RATE_LIMITED e INTERNAL podem voltar de qualquer ferramenta, então a linha Errors sob cada ferramenta abaixo nomeia o que é específico daquela ferramenta.
list
Lista uma pasta, ou pesquisa todos os workspaces concedidos por caminhos que correspondam a uma substring.
Argumentos
workspace? string workspace slug; omit to fan out over every granted workspace
path string default "" (workspace root)
recursive boolean default false
include_deleted boolean default false
limit integer 1..1000, default 500, applied per workspace
cursor? string opaque; requires an explicit workspace
q? string 1..1024 chars, case-insensitive substring of the full path; implies recursive
Retorna
{
"results": [
{
"workspace": { "id": "...", "slug": "research" },
"entries": [
{
"path": "notes/todo.md",
"type": "file",
"size": 1284,
"version": 7,
"modified_at": "2026-08-05T09:12:44Z",
"modified_by_label": "research-agent",
"by_actor": "agent",
"deleted": true
}
],
"next_cursor": "..."
}
]
}
type é "file" ou "folder". size, version, modified_at, modified_by_label, by_actor e deleted são opcionais por entrada.
Erros: INVALID_PATH.
Notas
resultsé sempre um array de blocos por workspace, mesmo quando o token tem permissão para exatamente um workspace. Não escreva um cliente que espere um arrayentriessimples.- Passar
cursordurante a expansão retornaINVALID_PATHcomreason: "cursor_requires_workspace". Fixe o workspace antes de paginar. - Pastas são sintetizadas a partir de prefixos de caminho. Não há registros de pasta para criar ou excluir.
read
Lê um arquivo, seja a versão atual ou uma anterior.
Argumentos
workspace? string
path string
version? integer defaults to the current version
Retorna, inline, quando o tamanho bruto é 262144 bytes ou menos e o tipo mime é texto:
{
"path": "notes/todo.md",
"version": 7,
"size": 1284,
"mime_type": "text/markdown",
"encoding": "utf8",
"content": "..."
}
Retorna, para qualquer coisa maior ou binária:
{
"path": "datasets/corpus.tar.gz",
"version": 3,
"size": 431912448,
"mime_type": "application/gzip",
"download_url": "https://...",
"url_expires_at": "2026-08-05T09:27:00Z"
}
Erros: NOT_FOUND (com deleted: true e last_version quando o caminho está com tombstone), INVALID_PATH.
Notas
- O formato da resposta muda com base no tamanho e no tipo mime, não em uma flag que você passa. Acima de 256 KiB, ou para qualquer arquivo não-texto, você recebe um
download_urlválido por 15 minutos em vez de conteúdo inline. Lide com ambos os formatos.
grep
Pesquisa o conteúdo de arquivos com uma expressão regular.
Argumentos
workspace? string
path? string search a single file
prefix? string search one folder; omit both path and prefix to search the whole workspace
pattern string min 1 char, RE2 syntax
case_sensitive boolean default false
context_lines integer 0..10, default 2
max_matches integer 1..200, default 50
Retorna
{
"matches": [
{
"path": "notes/todo.md",
"line": 42,
"text": "TODO: rotate the staging token",
"before": ["..."],
"after": ["..."]
}
],
"files_scanned": 128,
"files_skipped_binary": 3,
"files_skipped_too_large": 0,
"truncated": false
}
Erros: INVALID_PATTERN, INVALID_PATH.
Notas
- Padrões são RE2, então não há backreferences nem lookaround. Um padrão inválido retorna
INVALID_PATTERN. - Correspondências são encontradas apenas dentro de linhas únicas. Um padrão que atravessa uma quebra de linha nunca corresponderá.
- Uma entrada por linha correspondente, como
grep -n, não importa quantas ocorrências essa linha contenha. truncated: truesignifica que a varredura atingiu seu orçamento e os resultados são parciais. Estreite oprefixou aperte o padrão.- Números de linha são apenas para exibição. Nunca cole um em
edit'sold_str.
history
Lista as versões de um arquivo, da mais nova para a mais antiga.
Argumentos
workspace? string
path string
limit integer 1..1000, default 50
cursor? string digits only
Retorna
{
"versions": [
{
"version": 7,
"op": "write",
"size": 1284,
"content_hash": "...",
"created_at": "2026-08-05T09:12:44Z",
"by_label": "research-agent",
"by_actor": "agent",
"moved_from": "drafts/todo.md",
"purged": false,
"restorable_until": "2027-08-05T09:12:44Z"
}
],
"next_cursor": "182734"
}
op é um de write, edit, move, delete, restore. moved_from, by_actor e restorable_until são opcionais.
Erros: NOT_FOUND, INVALID_PATH.
Notas
- Da mais nova para a mais antiga, então
limit: 1é a forma mais barata de confirmar que uma escrita foi registrada. next_cursoré uma string opaca, nunca um número. Está ausente na última página, que é como você sabe que deve parar.purged: truesignifica que a retenção liberou o conteúdo daquela versão. A linha permanece para a trilha de auditoria, masrestorepara ela retornaNOT_FOUNDcomreason: "version_purged".
activity
Lista o que mudou em um workspace e qual agente mudou.
Argumentos
workspace? string
since? string RFC 3339 timestamp
path_prefix? string
limit integer 1..1000, default 100
cursor? string
Retorna
{
"events": [
{
"at": "2026-08-05T09:12:44Z",
"actor": "agent",
"by_label": "research-agent",
"by_actor": "agent",
"op": "write",
"path": "notes/todo.md",
"old_path": "drafts/todo.md",
"version": 7
}
],
"next_cursor": "9014522"
}
actor é um de agent, user, system. Da mais nova para a mais antiga.
op é write, edit, move, delete, restore, purge, lock, unlock ou grep. Varreduras do sistema também registram purge_retention e purge_workspace_delete, ambos sem caminho. Apenas write, edit, move, delete e um restore de arquivo único carregam um version; nos demais, é nulo. Observe que purge carrega um caminho real ou prefixo de pasta, então corresponde a um filtro path_prefix: se você está auditando uma pasta a partir deste feed, uma purga aparece junto com as escritas.
Erros: INVALID_PATH.
Notas
next_cursoré uma string opaca, nunca um número. Está ausente na última página, que é como você sabe que deve parar.- Isto é uma sondagem. Não há webhooks, nem gatilhos, nem push. Agentes coordenam chamando
activityem um intervalo, o que cabe confortavelmente dentro do limite de taxa em uma cadência de segundos a minutos. sinceé um timestamp, não um cursor, e dois eventos podem compartilhar um. Espere re-entrega ocasional e torne o trabalho idempotente. Veja examples/two-agent-handoff.md.
write
Cria ou substitui um arquivo com conteúdo inline.
Argumentos
workspace? string
path string
content string
encoding "utf8" | "base64" default "utf8"
mime_type? string
expected_version? integer fail instead of overwriting a concurrent change
override_lock boolean default false
Limite inline: 1 MiB decodificado. Qualquer coisa maior passa por request_upload.
Retorna
{
"path": "notes/todo.md",
"version": 8,
"size": 1301,
"content_hash": "...",
"deduplicated": false,
"unchanged": true
}
unchanged está presente apenas quando se aplica.
Erros: INVALID_PATH, VERSION_CONFLICT, LOCKED, QUOTA_EXCEEDED, TOO_LARGE.
Notas
- Escrever conteúdo byte-idêntico à versão atual é um no-op: retorna
unchanged: truee não cria nova versão. Para um trabalho agendado, vale registrar isso em voz alta, porque geralmente significa que o gerador não rodou. - Conteúdo idêntico a uma versão anterior cria uma nova versão.
- Escrever em um caminho com tombstone o ressuscita.
edit
Aplica substituições de string em um arquivo de texto existente sem reenviar o corpo inteiro.
Argumentos
workspace? string
path string
edits array of 1..20 objects:
old_str string min 1 char
new_str string
replace_all boolean default false
expected_version? integer
override_lock boolean default false
Arquivos de texto de até 16 MiB.
Retorna
{
"path": "notes/todo.md",
"version": 9,
"edits_applied": 2,
"replacements": [1, 3],
"size_before": 1301,
"size_after": 1288,
"context": "..."
}
unchanged está presente apenas quando se aplica.
Erros: STRING_NOT_FOUND, STRING_NOT_UNIQUE, NOT_EDITABLE, TOO_LARGE_FOR_EDIT, VERSION_CONFLICT, LOCKED, QUOTA_EXCEEDED, NOT_FOUND.
Notas
- As edições são aplicadas em ordem e confirmadas atomicamente como uma nova versão, então uma chamada com 20 edições é uma única entrada em
history, não vinte. Se qualquer edição falhar, nenhuma delas é aplicada. - Cada
old_strdeve corresponder exatamente uma vez, caso contrário você recebeSTRING_NOT_FOUNDouSTRING_NOT_UNIQUE. Definareplace_allquando quiser dizer todas as ocorrências. - Como as edições são aplicadas em ordem, um
old_strposterior deve corresponder ao texto como as edições anteriores o deixaram.
move
Move ou renomeia um arquivo.
Argumentos
workspace? string
from string
to string
expected_version? integer
overwrite boolean default false
override_lock boolean default false
Retornos
{ "from": "drafts/todo.md", "to": "notes/todo.md", "version": 1 }
version é a nova versão no destino.
Erros: NOT_FOUND, INVALID_PATH, VERSION_CONFLICT (com reason: "destination_exists"), LOCKED.
Notas
- O token precisa de acesso de escrita a ambos os caminhos. Uma regra de prefixo que cobre a origem, mas não o destino, falha com
PERMISSION_DENIED. - Um destino ativo com
overwrite: falseretornaVERSION_CONFLICTcomreason: "destination_exists". Essa falha é útil: dois workers disputando para reivindicar o mesmo item podemmovee o perdedor recebe um erro limpo em vez de trabalho duplicado.
delete
Cria um tombstone para um arquivo.
Argumentos
workspace? string
path string
expected_version? integer
override_lock boolean default false
Retornos
{ "path": "notes/todo.md", "version": 10, "unchanged": true }
unchanged está presente apenas quando se aplica.
Erros: NOT_FOUND, INVALID_PATH, VERSION_CONFLICT, LOCKED.
Notas
- Isso grava uma versão tombstone, não apaga o conteúdo. O arquivo permanece recuperável com
restoreenquanto a janela de histórico de versões do seu plano permitir. - Escrever no mesmo caminho posteriormente o ressuscita como uma nova versão no mesmo histórico.
listoculta caminhos com tombstone, a menos que você passeinclude_deleted: true.
restore
Restaura um arquivo para uma versão anterior, ou uma pasta inteira para um ponto no tempo.
Argumentos, forma de arquivo:
workspace? string
path string
to_version integer
override_lock boolean default false
Argumentos, forma de pasta:
workspace? string
prefix string
at string RFC 3339 timestamp in UTC, e.g. 2026-08-05T14:04:55Z
override_lock boolean default false
Retornos, forma de arquivo:
{ "path": "notes/todo.md", "version": 11 }
Retornos, forma de pasta:
{
"restored": 42,
"deleted": 3,
"affected_paths": ["content/pricing.md", "content/index.md"],
"total": 45
}
affected_paths é uma amostra limitada; total é a contagem real.
Erros: NOT_FOUND (com reason: "version_purged" quando a retenção já liberou a versão alvo), INVALID_PATH, LOCKED.
Notas
atdeve estar em UTC, terminando emZ, com milissegundos opcionais. Um offset UTC como+02:00é rejeitado mesmo sendo RFC 3339 válido, então converta antes de chamar.- A restauração acrescenta novas versões e nunca reescreve o histórico. As versões ruins permanecem em
history, então restaurar para o timestamp errado é em si restaurável, e restaurar duas vezes é seguro. - Na forma de pasta, arquivos que não existiam em
atrecebem tombstones de exclusão, contados pordeleted. Eles não são apagados e uma escrita posterior os traz de volta. - Não há simulação (dry run). Dimensione a operação com
liste confirme um único arquivo comhistoryprimeiro. Passo a passo: examples/folder-restore-after-bad-run.md.
lock
Obtém um lock consultivo em um caminho.
Argumentos
workspace? string
path string
Retornos
{ "path": "notes/todo.md", "expires_at": "2026-08-05T09:17:44Z" }
Erros: LOCKED, INVALID_PATH.
Notas
- Consultivo e de 5 minutos. Chame
locknovamente com o mesmo token para renovar. - Locks nunca bloqueiam leituras. Um lock válido estrangeiro faz as escritas retornarem
LOCKEDcomlocked_by_labeleexpires_at, a menos que o chamador passeoverride_lock: true, o que é registrado no feed de atividades. - O arquivo não precisa existir, então você pode bloquear um caminho que está prestes a criar.
- Para trabalho que pode ser tornado idempotente, prefira uma reivindicação com
moveem vez de um lock: ela sobrevive a uma falha, e um TTL de 5 minutos não.
unlock
Libera um lock que este token detém.
Argumentos
workspace? string
path string
Retornos
{ "path": "notes/todo.md", "released": true }
Erros: PERMISSION_DENIED (o lock pertence a outro token), INVALID_PATH.
Notas
- Desbloquear um caminho sem lock retorna
released: true, nãoNOT_FOUND. A chamada não diz nada sobre se um lock existia, então não é uma forma de perguntar quem detém um.
request_upload
Inicia um upload para conteúdo grande demais para write inline. Primeiro de dois passos; veja Large file uploads.
Argumentos
workspace? string
path string
size integer positive, the exact byte count of the file
mime_type? string
expected_version? integer
override_lock boolean default false
Retornos
{
"upload_id": "...",
"put_url": "https://...",
"url_expires_at": "2026-08-05T09:27:00Z",
"max_size": 1073741824
}
Erros: TOO_LARGE, QUOTA_EXCEEDED, VERSION_CONFLICT, LOCKED, INVALID_PATH.
Notas
- A URL PUT pré-assinada é válida por 15 minutos e o registro de upload por 1 hora. Não há upload retomável ou multiparte: se o PUT falhar, comece novamente de
request_upload. sizedeve ser a contagem exata de bytes. Ela é re-verificada emfinalize_upload.
finalize_upload
Confirma um arquivo enviado como uma nova versão. Segundo de dois passos.
Argumentos
workspace? string
upload_id string
Retornos
{
"path": "datasets/corpus.tar.gz",
"size": 431912448,
"version": 3,
"content_hash": "..."
}
Erros: UPLOAD_EXPIRED, VERSION_CONFLICT, QUOTA_EXCEEDED, TOO_LARGE.
Notas
- Tamanho e
expected_versionsão ambos re-verificados aqui, então umVERSION_CONFLICTpode aparecer na finalização mesmo querequest_uploadtenha sido bem-sucedido. Alguém escreveu no caminho enquanto você enviava; comece novamente derequest_upload. - Chamar finalize uma segunda vez retorna
UPLOAD_EXPIRED.
Erros
Falhas de domínio retornam como um resultado de ferramenta normal carregando isError: true, cujo conteúdo de texto é JSON:
{ "code": "VERSION_CONFLICT", "message": "...", "current_version": 9 }
Elas nunca são erros de protocolo JSON-RPC. Agentes e clientes devem ramificar em code.
A validação de argumentos falha da mesma forma, mas o texto não é JSON. Passar um argumento do tipo errado retorna isError: true com uma string em inglês simples como MCP error -32602: Input validation error: Invalid arguments for tool activity: ..., produzida pela camada MCP antes de a requisição chegar ao Layven. Então faça o parse defensivamente: um resultado isError cujo texto não parseia como JSON é um bug na sua chamada, não um erro de domínio do Layven. upload/layven-upload.mjs faz exatamente isso, caindo para code: "UNKNOWN" com o texto bruto como mensagem.
| Código | Significado | Extras |
|---|---|---|
NOT_FOUND | Caminho, versão ou workspace ausente | workspaces (os slugs do token) quando um slug de workspace não resolve; deleted: true e last_version em um caminho com tombstone; reason: "version_purged" em uma versão purgada |
PERMISSION_DENIED | Token não tem o nível de acesso, ou uma regra de prefixo bloqueia o caminho | required |
INVALID_PATH | Caminho falha na normalização | reason |
VERSION_CONFLICT | expected_version não correspondeu, ou o destino existe | current_version, às vezes reason (por exemplo destination_exists) |
LOCKED | Outro token detém um lock válido | locked_by_label, expires_at |
QUOTA_EXCEEDED | Organização excedeu sua cota de armazenamento | limit_bytes, used_bytes |
TOO_LARGE | Conteúdo inline acima do limite, ou arquivo acima de 1 GiB | max_bytes |
UPLOAD_EXPIRED | Finalize chamado em um upload expirado ou já consumido | |
RATE_LIMITED | Limite de taxa do token ou da organização atingido | retry_after_ms |
INTERNAL | Falha inesperada do servidor | request_id |
STRING_NOT_FOUND | edit: old_str não está presente no arquivo | dica |
STRING_NOT_UNIQUE | edit: old_str correspondeu mais de uma vez e replace_all não foi definido | |
NOT_EDITABLE | edit: o arquivo não é texto | |
TOO_LARGE_FOR_EDIT | edit: arquivo acima de 16 MiB | |
INVALID_PATTERN | grep: o padrão não é RE2 válido |
RATE_LIMITED é o único código que vale a pena tentar novamente automaticamente: durma retry_after_ms, então tente de novo.
Limites
| Limite | Valor |
|---|---|
| Escrita inline | 1 MiB decodificado; conteúdo maior passa por request_upload |
| Leitura inline | 256 KiB e um tipo MIME de texto, caso contrário uma URL de download |
| Edição | Arquivos de texto até 16 MiB, até 20 edições por chamada |
| Grep | 8 MiB por arquivo verificado, 500 arquivos candidatos por chamada, resultados parciais além do orçamento de tempo |
| Tamanho máximo de arquivo | 1 GiB |
| URL PUT pré-assinada | 15 minutos |
| Registro de upload | 1 hora |
| URL de download | 15 minutos |
| Comprimento do caminho | 1024 bytes |
| TTL do lock | 5 minutos, renovável |
| Limite de taxa | 600 requisições por minuto por token, 3000 por minuto por organização |
Exceder um limite de taxa retorna RATE_LIMITED com retry_after_ms.
Caminhos e versionamento
Caminhos são UTF-8, separados por / e sensíveis a maiúsculas/minúsculas. Eles são normalizados na entrada:
- sem barra inicial:
/a/btorna-sea/b - sem barras duplicadas
- sem segmentos
.ou.., e sem segmentos vazios - sem barra final em um arquivo
- sem caracteres de controle
- máximo de 1024 bytes
Qualquer outra coisa retorna INVALID_PATH com um reason. Diretórios são implícitos: não há registros de pasta, e list sintetiza pastas a partir de prefixos de caminho.
Versionamento. Cada mutação cria uma nova versão, numerada por arquivo. delete grava uma versão tombstone. move cria uma versão no destino e cria tombstone na origem. restore acrescenta uma nova versão reproduzindo um estado anterior. O histórico é somente-acréscimo e nunca é reescrito, e é por isso que uma restauração ruim é em si restaurável.
Concorrência otimista. O padrão é último-escrita-vence, o que é seguro porque nada é perdido. Quando você quer que uma escrita falhe em vez de sobrescrever uma mudança concorrente, passe expected_version com a versão que você leu. Uma incompatibilidade retorna VERSION_CONFLICT com current_version no payload, para que o chamador possa reler e decidir.
Locks. lock obtém um lock consultivo de 5 minutos, renovado chamando lock novamente com o mesmo token. Um lock válido estrangeiro faz as escritas retornarem LOCKED com locked_by_label e expires_at; override_lock: true prossegue mesmo assim e é registrado no feed de atividades. Locks nunca bloqueiam leituras.
Permissões
Cada token recebe acesso a workspaces específicos em um de três níveis:
| Nível | Ferramentas |
|---|---|
ro | list, read, grep, history, activity |
rw | tudo em ro, mais write, edit, move, delete, restore, lock, unlock, request_upload, finalize_upload |
admin | reservado para futura gestão de workspaces |
Uma concessão pode carregar regras de prefixo opcionais que restringem um token a pastas específicas, expressas como listas allow ou deny. Negar vence permitir. move exige permissão tanto no caminho de origem quanto no de destino.
Dê a cada agente seu próprio token. É isso que torna by_label em list, history e activity legíveis, e é o que permite revogar um agente sem afetar os outros.
Uploads de arquivos grandes
write inline tem limite de 1 MiB. Acima disso, envie em três passos.
1. Peça uma URL. Chame request_upload com a contagem exata de bytes:
{ "path": "datasets/corpus.tar.gz", "size": 431912448, "mime_type": "application/gzip" }
{
"upload_id": "...",
"put_url": "https://...",
"url_expires_at": "2026-08-05T09:27:00Z",
"max_size": 1073741824
}
2. Faça PUT dos bytes em put_url. Isso é um PUT HTTP simples do arquivo bruto, não uma chamada MCP. A URL é válida por 15 minutos.
3. Confirme. Chame finalize_upload:
{ "upload_id": "..." }
{
"path": "datasets/corpus.tar.gz",
"size": 431912448,
"version": 3,
"content_hash": "..."
}
Por que não há SDK
Não há biblioteca cliente Layven e não haverá. Layven é um servidor MCP hospedado: você aponta seu cliente para uma URL e seu agente recebe 14 ferramentas, sem código para escrever e nada para manter atualizado. Esta é a única exceção. O fluxo de upload tem um passo intermediário que é um PUT HTTP bruto, e um cliente MCP não pode emitir um, então enviamos um único script sem dependências para isso. Copie, leia, altere. É MIT.
upload/layven-upload.mjs
Node 18 ou mais novo. Sem dependências, sem instalação.
LAYVEN_TOKEN=agd_your_agent_token \
node upload/layven-upload.mjs ./corpus.tar.gz datasets/corpus.tar.gz \
[--workspace slug] [--mime type] [--expected-version N] [--override-lock] \
[--url https://api.layven.io/mcp]
LAYVEN_TOKEN é obrigatório. --url tem como padrão https://api.layven.io/mcp.
Execute seus testes a partir da raiz do repositório com:
node --test
Exemplos
- examples/two-agent-handoff.md: o agente A deixa o trabalho no drive, o agente B o pega consultando
activity. - examples/nightly-write-and-verify.md: um agente acionado por cron que escreve um artefato e prova que a gravação foi concluída.
- examples/folder-restore-after-bad-run.md: faça triagem de uma execução ruim de agente e reverta uma pasta para um timestamp.
Planos
| Free | Pro $19/mo | Scale $49/mo | Enterprise | |
|---|---|---|---|---|
| Armazenamento | 5 GB | 100 GB | 500 GB | Personalizado |
| Histórico de versões | 30 dias | 1 ano | Ilimitado | Ilimitado |
| Registro de atividades | 30 dias | 1 ano | 1 ano | Ilimitado |
| Espaços de trabalho | 1 | 5 | 25 | Ilimitado |
| Tokens | 2 | 25 | 100 | Ilimitado |
| Assentos | 1 | 3 | 10 | Ilimitado |
| Tamanho máximo de arquivo | 1 GiB | 1 GiB | 1 GiB | 1 GiB |
| Limite de taxa | 600 req/min/token | 600 req/min/token | 600 req/min/token | 600 req/min/token |
Preço fixo. Sem medidores, sem créditos.
Residência de dados
Seus arquivos são armazenados na OVHcloud em Gravelines, França, e são criptografados em repouso. Nenhuma IA de terceiros ou API de modelo toca no seu conteúdo. Você pode exportar tudo como arquivos simples, e a exclusão é uma exclusão real.
Versionamento
A versão em server.json e no changelog corresponde à versão que o servidor informa em initialize, para que você possa sempre verificar com o que está falando. Alterações na documentação que não acompanham uma alteração no servidor não incrementam a versão.
Veja CHANGELOG.md.
Suporte
Erros nestes documentos, nos exemplos ou no auxiliar de upload: abra uma issue. Dúvidas sobre conta, cobrança ou dados: info@layven.io.
Licença
O MIT cobre este repositório: a documentação, os exemplos e o auxiliar de upload. O serviço Layven em si é de código fechado.