Structured key:value protocol for machine-to-machine LLM communication
Project description
lio-lang
Protocolo estruturado key:value para comunicacao maquina-a-maquina com LLMs. Substitui a prosa que o modelo produz entre tool calls e em respostas finais por um formato compacto parecido com JSON, voltado para outputs que serao consumidos por codigo, agentes ou automacao em vez de lidos por humanos.
import lio
prompt = lio.system_prompt(mode="agentic", language="en")
report = lio.validate(model_text) # compliance check
natural = lio.render(lio_text) # LIO -> natural for display
metrics = lio.measure( # cost/savings math
natural_input_tokens=582, natural_output_tokens=25378,
lio_input_tokens=4311, lio_output_tokens=5488,
model="claude-opus-4-6",
)
Sem dependencias obrigatorias. Licenca Apache 2.0. Python 3.11+.
Instalacao
pip install lio-lang # core, zero dependencias
pip install lio-lang[anthropic] # com wrapper da SDK Anthropic
pip install lio-lang[benchmarks] # com deps para rodar os benchmarks
# Ou com uv
uv sync
uv sync --extra anthropic
uv sync --extra benchmarks
Quickstart
import anthropic
import lio
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-4-6",
max_tokens=16000,
system=lio.system_prompt(mode="single_shot", language="en"),
messages=[{"role": "user", "content": "Write a Python prime filter function"}],
)
raw_text = "".join(b.text for b in response.content if b.type == "text")
# Check the response is compliant LIO
report = lio.validate(raw_text)
print(f"compliant: {report.compliant} (score {report.score})")
# Convert LIO to natural language for human display (no extra API call)
print(lio.render(raw_text, language="en"))
Exemplos rodaveis em examples/:
# Exercita toda a API publica, funciona offline e online
uv run examples/quickstart.py # sem API key: so offline
uv run --extra anthropic examples/quickstart.py # com API key: online tambem
# Compara baseline natural vs LIO roundtrip lado a lado
uv run --extra anthropic examples/full_flow.py --prompt "Faca uma funcao de ordenacao"
uv run --extra anthropic examples/full_flow.py --prompt "Write a debounce function" --language en
API publica
| Funcao | Proposito |
|---|---|
lio.system_prompt(mode, language) |
Retorna a string do system prompt LIO. mode="agentic" (multi-turno com tools) ou "single_shot". language="en" ou "pt". |
lio.validate(text) |
Checa se um text block e LIO valido. Retorna ComplianceReport(compliant, score, reasons). |
lio.render(lio_text, language) |
Converte LIO de volta para linguagem natural para display. Rule-based, zero chamadas de API. Fallback seguro retorna o input inalterado. |
lio.measure(...) |
Calcula economia de custo a partir de contagens pareadas de tokens. Retorna EconomyMetrics com custo, economia percentual, breakdown de input/output. |
lio.middleware.wrap_call |
Decorator que injeta o system prompt LIO em qualquer funcao de chamada LLM e opcionalmente roda um callback de telemetria. |
Exemplo de middleware
import lio
from lio.middleware import wrap_call
def telemetry(response):
text = "".join(b.text for b in response.content if b.type == "text")
r = lio.validate(text)
print(f"[lio] compliance={r.score:.2f}")
@wrap_call(mode="agentic", language="en", on_response=telemetry)
def call_claude(messages, **kwargs):
return client.messages.create(
model="claude-opus-4-6",
max_tokens=16000,
messages=messages,
**kwargs,
)
# Cada chamada vai automaticamente:
# 1. receber o system prompt LIO injetado
# 2. ser validada via callback
response = call_claude(messages=[{"role": "user", "content": "..."}])
Filosofia
LIO estrutura informacao, nao comprime.
O objetivo nao e "economizar tokens a qualquer custo". E transferir a mesma informacao que linguagem natural transferiria, eliminando o overhead de apresentacao: prosa, markdown, pedagogia, cortesia, decoracao visual.
O que cai fora sao as sobras de linguagem natural, nao os dados.
Detalhes tecnicos que perderiam funcionalidade se abreviados
(paths absolutos, identificadores exatos, valores de config, schemas)
sao preservados. Quando a resposta precisa de valores que o consumidor
vai substituir, usa-se placeholders explicitos <REPLACE:nome> em vez
de tentar comprimir com truques que colidem com sintaxe da linguagem
alvo.
A analogia correta e com JSON, nao com compressao lossy:
LIO esta para prosa assim como JSON esta para XML-verboso: mesma informacao, sem a gordura de apresentacao. JSON nao e "compressao lossy de XML"; e uma estruturacao diferente da mesma informacao. LIO tem a mesma relacao com a prosa de LLM.
Consequencias praticas:
- Uma resposta LIO pode ser longa se a informacao exige.
- Use quantos campos forem necessarios para manter precisao tecnica.
- Alternativas validas sao preservadas via campo
variant. - O modelo mantem liberdade de planejamento, nao e constrangido a "escolher uma resposta e descartar as outras".
Sintaxe
Gramatica minima
field = key ':' value
value = escalar | '[' lista ']' | '{' objeto '}' | '<REPLACE:' nome '>'
text_block = sequencia de fields, separados por espaco ou newline
Escalares sao literais. Listas usam virgula. Objetos usam virgula entre pares.
Campos reservados
Uma letra para a estrutura base:
| Campo | Uso |
|---|---|
T |
task type |
O |
object / target |
P |
params |
C |
context |
F |
expected format |
X |
constraints |
S |
status (ok, err, partial) |
R |
result |
D |
data |
W |
warning |
E |
error |
Q |
query |
N |
count |
Palavras-chave para semantica adicional:
| Campo | Uso |
|---|---|
step |
acao atual (loops agenticos) |
next |
proxima acao |
fix |
correcao proposta |
issues |
lista de problemas encontrados |
causes |
lista de causas possiveis |
variant |
resposta alternativa valida |
note |
observacao nao obvia |
code |
bloco de codigo (passa intacto) |
steps |
sequencia de passos |
Voce pode introduzir campos novos quando fizer sentido.
Placeholders explicitos
Quando a resposta precisa de valores que o consumidor deve substituir,
use <REPLACE:nome_descritivo>. Por que nao outras opcoes:
$variavelou${variavel}colidem com bash, nginx, make{{variavel}}colide com Jinja, Mustache, Go templates__variavel__fragil, nao se destaca<REPLACE:nome>angle brackets sao slot universal,REPLACEe explicito, nenhuma linguagem mainstream usa esse token literal
Exemplo (config nginx com SSL):
S:ok R:nginx_config
code:{
server {
listen 443 ssl http2;
server_name <REPLACE:your_domain>;
ssl_certificate /etc/letsencrypt/live/<REPLACE:your_domain>/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/<REPLACE:your_domain>/privkey.pem;
location / { proxy_pass http://localhost:3000; }
}
}
W:run_certbot_first->certbot --nginx -d <REPLACE:your_domain>
O que LIO nao tem
O mesmo que JSON nao tem: markdown headers, tabelas, listas bullet, emoji decorativo, blocos de citacao, negrito/italico, preambulo ("Aqui esta..."), cortesia ("Espero que ajude"), ou prosa explicativa redundante com o conteudo.
Codigo dentro de code:{} passa intacto, pode conter qualquer sintaxe
da linguagem alvo.
Quando usar LIO
Use onde o consumidor da resposta nao e um humano, ou onde a resposta sera processada por codigo antes de chegar em humano.
Casos ideais:
- Pipelines agentic (agente LLM agente) - nenhum humano le o intermediario
- Workflows automatizados (n8n, Make, Zapier)
- RAG chains - query, retrieve, LLM, resposta estruturada downstream
- Multi-agent systems onde agentes conversam entre si
- Batch processing - milhares de chamadas identicas em formato
- Coding agent plugins - raciocinio intermediario entre tool calls
Nao use para:
- Chat direto com humano - o humano precisa ler a resposta
- Tarefas criativas (escrita, brainstorm) - a verbosidade e o produto
- Educacao e explicacoes - tokens de explicacao sao o produto
- Respostas onde a prosa e o valor (emails, documentacao)
Padroes de integracao
1. Injecao direta do system prompt
O mais simples. Funciona com qualquer SDK:
import anthropic
import lio
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-4-6",
max_tokens=16000,
system=lio.system_prompt(mode="agentic", language="en"),
messages=[{"role": "user", "content": "..."}],
)
2. Middleware decorator
Se voce ja tem uma funcao que chama a LLM, so decora:
import lio
from lio.middleware import wrap_call
@wrap_call(mode="agentic", language="en", on_response=lambda r: print("[lio] ok"))
def call_llm(messages, **kwargs):
return client.messages.create(
model="claude-opus-4-6",
max_tokens=16000,
messages=messages,
**kwargs,
)
response = call_llm(messages=[{"role": "user", "content": "..."}])
3. Renderizacao para UI
Se o consumidor final e humano, converta LIO de volta para natural antes de mostrar:
text = "".join(b.text for b in response.content if b.type == "text")
human_view = lio.render(text, language="en")
print(human_view)
Transformacao rule-based local, sem chamada de API. Cobre os padroes
comuns (S:ok code:{...}, issues:[...] fix:[...], objetos aninhados,
listas) e faz fallback seguro retornando o input inalterado quando nao
reconhece a forma.
Benchmarks
Bateria de 15 tarefas single-shot contra claude-opus-4-6, pareando
prompts em linguagem natural com prompts em LIO. Roda com:
python -m benchmarks.run # 15 tarefas, ~$1
python -m benchmarks.multi_turn # sessao agentic, ~$0.15
python -m benchmarks.fidelity # LLM-as-judge, ~$0.30
Resultados representativos
| Cenario | Compliance | Fidelidade | Economia custo | Economia output |
|---|---|---|---|---|
| Single-shot, 15 tarefas | 100% | 95% | 69-75% | 79-82% |
| Multi-turn agentic, 3 turnos | 100% | - | 40-55% | 55-73% |
| Roundtrip Fibonacci (example full_flow) | 100% | - | 70-75% | 83-87% |
Compliance e medido pelo validator local (lio.validate). Fidelidade
e medida com LLM-as-judge calibrado em benchmarks/fidelity.py.
Economia de output varia por categoria:
| Categoria | Economia de output |
|---|---|
| debug | ~70% |
| cfg | ~85% |
| refactor | ~85% |
| code | ~80% |
| analyze | ~65% |
Economia efetiva varia com a proporcao de text vs tool_use no output total. Para coding agents com uso pesado de tools, a economia por sessao tipicamente fica entre 30-50%, pois LIO so afeta os text blocks do modelo - tool_use blocks JSON permanecem identicos.
Limites conhecidos
-
Economia depende do shape da tarefa. Tarefas prose-heavy (explicacoes, analises, debug) capturam 60-75%. Tarefas tool-heavy (coding agents com muito read/write/bash) capturam 30-50%. Tarefas onde o output e dominado por codigo cru dentro de
code:{}capturam 20-30% (o codigo passa intacto). -
Input savings sao frequentemente negativos. O system prompt LIO adiciona ~500 tokens por chamada. Em prompts curtos isso domina o input. A economia vem do output, que custa 5x mais que input no Opus. Em sessoes longas com historico acumulado, input savings vira positivo.
-
LIO requer modelos inteligentes. Testado em Opus 4.6 e Sonnet 4.6. Nao recomendado para Haiku - o overhead cognitivo de seguir o protocolo nao compensa para modelos menores. Haiku pode ser usado como decoder LIO->natural barato.
-
Drift de compliance em prompts-gatilho. Palavras como "relatorio"/"report" no prompt do usuario ativam priors fortes para output em markdown. O validator detecta drift (inclui detecao de markdown inclusive dentro de
code:{}blocks), e a filosofia "estrutura nao compressao" mitiga, mas vale atencao. -
Fidelidade depende de juiz calibrado. LLM-as-judge pode penalizar LIO por "omissoes" que sao na verdade over-delivery da resposta natural (info que o usuario nao pediu). O juiz em
benchmarks/fidelity.pye calibrado para ancorar o julgamento na pergunta do usuario, nao na resposta natural de referencia.
Estrutura do repositorio
lio-lang/
├── lio/
│ ├── __init__.py # API publica
│ ├── protocol.py # factory de system prompts
│ ├── validator.py # compliance checker
│ ├── render.py # LIO -> natural (rule-based)
│ ├── metrics.py # calculo de economia + tabela de pricing
│ ├── client.py # wrapper opcional da Anthropic SDK
│ ├── languages/
│ │ ├── en.py # prompts em ingles
│ │ └── pt.py # prompts em portugues
│ └── middleware/
│ └── generic.py # wrap_call decorator
├── tests/
│ ├── test_validator.py
│ ├── test_render.py
│ └── test_metrics.py
├── benchmarks/
│ ├── tasks.jsonl # 15 tarefas pareadas
│ ├── run.py # benchmark single-shot
│ ├── multi_turn.py # benchmark agentic
│ ├── fidelity.py # LLM-as-judge
│ └── compare.py # relatorio comparativo
├── examples/
│ ├── quickstart.py # exercita toda a API (offline + online)
│ └── full_flow.py # comparacao natural vs LIO roundtrip
├── pyproject.toml
├── LICENSE # MIT
└── README.md # este arquivo
Desenvolvimento
git clone https://github.com/estevaofon/lio-lang
cd lio-lang
uv sync --extra dev # ou: pip install -e .[dev]
# Rodar os testes
pytest tests/
# Rodar os exemplos (offline, sem API key)
uv run examples/quickstart.py --offline
# Rodar os exemplos com API real (precisa ANTHROPIC_API_KEY em .env)
uv run --extra anthropic examples/quickstart.py
uv run --extra anthropic examples/full_flow.py --prompt "sua pergunta"
# Rodar benchmark completo (custo ~$1.50 em API)
uv run --extra benchmarks python -m benchmarks.run
uv run --extra benchmarks python -m benchmarks.multi_turn
uv run --extra benchmarks python -m benchmarks.fidelity
Licenca
Apache License 2.0. Ver LICENSE e NOTICE.
Copyright 2026 Estevao Fonseca.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file lio_lang-0.1.0.tar.gz.
File metadata
- Download URL: lio_lang-0.1.0.tar.gz
- Upload date:
- Size: 33.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.7.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9dcc0fbddf7beadf3074a929555e89bc6f5722a81753d0fb71a8026db96f6fa3
|
|
| MD5 |
a428bd4779bf5dc6c8770166d95ae8a3
|
|
| BLAKE2b-256 |
4c7b8dda180f108e31ad72cadc7137356aff91b832e1a97ccd51045b11679c2e
|
File details
Details for the file lio_lang-0.1.0-py3-none-any.whl.
File metadata
- Download URL: lio_lang-0.1.0-py3-none-any.whl
- Upload date:
- Size: 27.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.7.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e7ec5f6a8b0dec53f1ced094911a55d9a37aae535251ae6988f4b26fe0930aa6
|
|
| MD5 |
d7a50ecd6f95c85f4fbf38bedeb0f554
|
|
| BLAKE2b-256 |
b1b965c6860373637071f0bb009b1011b58b9c30069ba831f18f550b1bad5fb2
|