Multi-item documentation

This commit is contained in:
2026-09-18 23:35:05 -03:00
parent 3ebdaacabc
commit 2ad9afd974
19 changed files with 1156 additions and 1043 deletions

View File

@@ -1,85 +1,90 @@
# Implementação prática — MCP Multi-Item
Este documento mostra o caminho mínimo para adicionar uma operação multi-item a um agente sem criar lógica paralela no código do agente.
Este documento mostra como adicionar uma operação multi-item sem criar lógica paralela no agente e sem alterar desnecessariamente contratos já existentes.
## 1. Modele uma única operação lógica
Exemplo de requisito:
```text
quero cancelar Produto A, Produto B e Produto C
```
A operação lógica deve continuar sendo uma só:
A operação lógica continua sendo uma só. Não crie tools/intents por item nem loops no Agent.
```text
cancelar_produtos
## 2. Escolha o contrato natural da operação
### Opção A — parâmetro escalar
Use quando a interface já recebe um `subject`, `id`, `query` ou expressão que pode representar uma ou várias entidades:
```yaml
tools:
cancelar_vas_avulso:
args_schema:
subject:
type: string
```
Não crie `cancelar_produto_1`, `cancelar_produto_2`, loops no agent ou intents artificiais por item.
Entrada:
## 2. Declare a coleção em `tools.yaml`
```text
subject = "Produto A, Produto B, Produto C"
```
### Opção B — coleção explícita
Use quando a API/tool é naturalmente batch:
```yaml
tools:
cancelar_produtos:
description: Cancela um ou mais produtos do cliente.
mcp_server: contas
enabled: true
tool_type: action
confirmation_required: true
requires: [items]
args_schema:
items:
type: array
label: os produtos
description: Lista de produtos a cancelar.
user_prompt: Quais produtos deseja cancelar?
```
Também é aceito `type: list` quando o projeto já usa essa forma.
**Não transforme uma tool escalar em array apenas para obter suporte multi-item.**
## 3. Use a policy transacional existente
## 3. Use a policy existente
Exemplo escalar:
```yaml
tool_policies:
cancelar_produtos:
cancelar_vas_avulso:
operation_type: transactional
require_confirmation: true
requires: [items]
requires:
- subject
pre_validation:
enabled: true
tool: validar_produtos_cancelamento
tool: validar_vas_subject
fail_open: false
```
Nenhuma chave específica de multi-item é necessária.
## 4. Canonicalize os itens no MCP validator
## 4. Canonicalize/expanda no validator quando necessário
Entrada possível:
Entrada:
```json
{
"items": ["produto a", "produto b", "produto c"]
}
{"subject": "produto a, produto b, produto c"}
```
Saída recomendada:
Saída possível:
```json
{
"eligible": true,
"status": "ELIGIBLE",
"transaction_decision": {
"resolved_arguments": {
"subject": "Produto A, Produto B, Produto C",
"items": [
{"name": "Produto A", "id": "1001"},
{"name": "Produto B", "id": "1002"},
{"name": "Produto C", "id": "1003"}
]
},
"target_tool": "cancelar_produtos",
"confirmation_message": "Você confirma o cancelamento de Produto A, Produto B e Produto C?"
}
}
@@ -97,30 +102,19 @@ B = inválido
C = válido
```
Se A e C ainda podem ser executados, não use simplesmente:
Com `fail_open: false`, isto bloquearia tudo:
```json
{
"eligible": false,
"reason": "B inválido"
}
{"eligible": false, "reason": "B inválido"}
```
Isso encerraria a transação inteira.
Quando A e C ainda podem ser executados, mantenha a transação globalmente elegível e preserve o estado individual dos itens.
Prefira manter a transação elegível quando houver item acionável e preservar informação suficiente para a tool primária produzir o resultado final por item.
## 6. Execute no MCP Server ou workflow
## 6. Execute a coleção no MCP Server ou workflow
A tool/workflow pode receber `subject` e expandir internamente, ou receber `items[]` já canonicalizado.
### Backend com API batch
```python
async def cancelar_produtos(items):
response = await backend.cancel_batch(items)
return normalize_results(response)
```
### Backend com API apenas unitária
### Backend com API unitária
```python
async def cancelar_produtos(items):
@@ -128,26 +122,16 @@ async def cancelar_produtos(items):
for item in items:
try:
response = await backend.cancel_one(item)
results.append({
"name": item["name"],
"success": True,
"response": response,
})
results.append({"name": item["name"], "success": True, "response": response})
except Exception as exc:
results.append({
"name": item["name"],
"success": False,
"error": str(exc),
})
results.append({"name": item["name"], "success": False, "error": str(exc)})
return {"results": results}
```
O loop acima pertence ao MCP/workflow, **não ao Agent**.
O loop pertence ao **MCP Server/workflow**, não ao Agent.
## 7. Retorne `results[]` por item
Contrato mínimo:
```json
{
"results": [
@@ -162,8 +146,6 @@ O framework aceita `success` ou `ok` booleano por item.
## 8. Resultado interpretado pelo framework
No exemplo anterior:
```text
items_count = 3
items_succeeded_count = 2
@@ -171,46 +153,24 @@ items_failed_count = 1
multi_item_status = PARTIAL_SUCCESS
```
O framework preserva os resultados terminais e fornece esse contexto para composição/presentation.
## 9. Workflow com etapa auxiliar
Estrutura recomendada:
```json
{
"status": "COMPLETED",
"output": {
"cancelar_produtos": {
"results": [
{"name": "A", "success": true},
{"name": "B", "success": true}
]
},
"registrar_analitica": {
"success": false,
"error": "analytics unavailable"
}
}
}
```
O resultado autoritativo da operação principal deve estar em:
```text
workflow.output[cancelar_produtos].results
workflow.output[tool_name].results
```
Assim uma falha auxiliar não converte A e B em falha operacional.
Assim uma falha auxiliar posterior não apaga itens já concluídos.
## 10. Checklist do desenvolvedor
Antes de criar código adicional, verifique:
- [ ] existe uma única tool lógica para a operação;
- [ ] a coleção está declarada como `array` ou `list` em `tools.yaml`;
- [ ] confirmação/pre-validation usam `tool_policies.yaml` existente;
- [ ] canonicalização pertence ao MCP validator;
- [ ] `tools.yaml` declara o contrato natural, escalar ou coleção;
- [ ] não existe requisito de `type: array` para habilitar multi-item;
- [ ] `tool_policies.yaml` mantém os `requires` reais do domínio;
- [ ] se um escalar representa vários itens, validator/tool/workflow faz a expansão;
- [ ] com `fail_open: false`, falha individual não bloqueia automaticamente todos os itens acionáveis;
- [ ] fan-out, se necessário, pertence ao MCP Server/workflow;
- [ ] a tool primária devolve `results[]`;
- [ ] cada item contém `success` ou `ok` booleano;
@@ -220,13 +180,13 @@ Antes de criar código adicional, verifique:
## 11. Testes mínimos recomendados
Cubra ao menos:
```text
1 item / sucesso
N itens / todos sucesso
N itens / sucesso parcial
N itens / todos falha
entrada escalar expandida para N itens
entrada batch explícita
item não canonicalizado
confirmação única para N itens
falha auxiliar após sucesso primário

View File

@@ -4,6 +4,8 @@ Capability de referência para operações MCP que precisam processar **mais de
> Esta capability é **framework-native**. Ela não exige um motor multi-item dentro do agente e não adiciona novos atributos obrigatórios a `tools.yaml` ou `tool_policies.yaml`.
> **Importante:** multi-item não é definido por `type: array`. O parâmetro de entrada pode ser escalar (`subject`, `id`, `query`) ou uma coleção. O que torna a execução multi-item é a resolução/execução de vários itens e o retorno por item em `results[]`.
## Quando usar
Use quando o usuário puder solicitar, por exemplo:
@@ -18,7 +20,7 @@ ou:
consulte os pedidos 1001, 1002 e 1003
```
O desenvolvedor deve modelar **uma operação lógica** que receba a coleção. O framework cuida de estado, confirmação e interpretação de resultados; o MCP Server ou workflow de domínio cuida da execução dos itens.
O desenvolvedor deve modelar **uma operação lógica**. O framework cuida de estado, confirmação e interpretação de resultados; validator/MCP Server/workflow cuidam da resolução e execução dos itens.
## Divisão de responsabilidades
@@ -30,25 +32,27 @@ Agent
↓
tools.yaml
declara array/list
declara o contrato natural da operação
pode ser escalar OU coleção
NÃO exige chave multi_item
↓
tool_policies.yaml
confirmação + pre-validation
usa o mesmo contrato transacional existente
confirmação + requires + pre-validation
NÃO possui sintaxe especial de multi-item
↓
MCP validator
resolve/canonicaliza os itens
resolve/canonicaliza itens
pode expandir subject/id/query em items[]
pode preencher transaction_decision.resolved_arguments
↓
MCP tool / workflow
executa os itens
executa 1 ou N itens
devolve results[] com success/ok por item
↓
@@ -66,70 +70,75 @@ LLM / Presentation
apresenta cada sucesso/falha
```
## Configuração mínima
## Configuração mínima — padrão escalar
Este padrão é útil quando a interface natural já usa `subject` e o validator expande múltiplas entidades.
### `tools.yaml`
O modo de configuração continua o mesmo. Declare o parâmetro como `array` ou `list`:
```yaml
tools:
cancelar_produtos:
description: Cancela um ou mais produtos.
cancelar_vas_avulso:
description: Cancela um ou mais VAS.
mcp_server: contas
enabled: true
tool_type: action
confirmation_required: true
requires: [items]
args_schema:
items:
type: array
label: os produtos
description: Produtos solicitados pelo cliente.
user_prompt: Informe quais produtos deseja cancelar.
subject:
type: string
```
Não é necessário criar configuração como:
### `tool_policies.yaml`
```yaml
tool_policies:
cancelar_vas_avulso:
operation_type: transactional
require_confirmation: true
requires:
- subject
pre_validation:
enabled: true
tool: validar_vas_subject
fail_open: false
```
Nenhuma chave abaixo existe ou é necessária:
```yaml
# NÃO EXISTE / NÃO É NECESSÁRIO
multi_item: true
multi_item_strategy: partial
fan_out: framework
```
### `tool_policies.yaml`
## Configuração alternativa — API batch
O contrato também continua o mesmo:
Quando a tool MCP recebe naturalmente uma coleção, `array/list` continua válido:
```yaml
tool_policies:
cancelar_produtos:
operation_type: transactional
require_confirmation: true
requires: [items]
pre_validation:
enabled: true
tool: validar_produtos_cancelamento
fail_open: false
args_schema:
items:
type: array
```
## Pre-validation e lista canônica
Isso é **uma opção de contrato**, não um pré-requisito para multi-item.
O validator pode transformar nomes informais em uma coleção canônica antes da confirmação:
## Pre-validation e expansão de itens
Um `subject` escalar pode ser transformado em argumentos canônicos:
```json
{
"eligible": true,
"transaction_decision": {
"resolved_arguments": {
"subject": "Produto A, Produto B, Produto C",
"items": [
{"name": "Produto A", "id": "1001"},
{"name": "Produto B", "id": "1002"},
{"name": "Produto C", "id": "1003"}
]
},
"target_tool": "cancelar_produtos",
"confirmation_message": "Você confirma o cancelamento de Produto A, Produto B e Produto C?"
}
}
@@ -137,21 +146,17 @@ O validator pode transformar nomes informais em uma coleção canônica antes da
### Validação parcial
`eligible` é global para a transação. Portanto, se pelo menos um item puder ser processado, o validator **não deve reprovar o lote inteiro apenas porque outro item falhou**.
`eligible` é global. Com `fail_open: false`, não retorne `eligible: false` apenas porque um item falhou se outros ainda são acionáveis.
Padrão recomendado:
1. `eligible: true` quando existe pelo menos um item acionável;
2. preservar/canonicalizar todos os itens necessários em `resolved_arguments`;
1. `eligible: true` enquanto houver pelo menos um item acionável;
2. preservar resolução/eligibilidade individual;
3. executar a operação primária;
4. retornar o resultado terminal individual em `results[]`.
Se nenhum item puder ser processado, `eligible: false` é apropriado.
4. produzir o resultado terminal individual em `results[]`.
## Resultado MCP esperado
A tool primária deve retornar `results[]` com `success` ou `ok` booleano por item:
```json
{
"results": [
@@ -162,50 +167,23 @@ A tool primária deve retornar `results[]` com `success` ou `ok` booleano por it
}
```
O framework deriva automaticamente:
O framework deriva automaticamente `SUCCESS`, `PARTIAL_SUCCESS` ou `FAILED`.
## Uma operação lógica, sem N chamadas no agente
São válidos:
```text
PARTIAL_SUCCESS
2 succeeded
1 failed
Agent -> cancelar(subject="A, B, C") -> validator/workflow -> results[]
```
Estados possíveis:
| Resultado dos itens | Status do framework |
|---|---|
| todos concluídos | `SUCCESS` |
| alguns concluídos e alguns falharam | `PARTIAL_SUCCESS` |
| todos falharam | `FAILED` |
## Uma chamada lógica, não N chamadas no agente
Se o backend suporta batch, prefira:
ou:
```text
Agent -> cancelar_produtos(items=[A,B,C]) -> MCP
Agent -> cancelar(items=[A,B,C]) -> MCP/workflow -> results[]
```
Se o backend possui apenas API unitária, o fan-out deve ficar encapsulado no MCP Server ou no workflow de domínio:
```text
Agent -> cancelar_produtos(items=[A,B,C])
|
v
MCP/workflow
/ | \
A B C
\ | /
results[]
```
Evite:
```python
# NÃO: lógica multi-item dentro do agente
for item in items:
await tool_router.call("cancelar_produto", {"item": item})
```
Se o backend possui apenas API unitária, o fan-out fica no MCP Server/workflow. Evite loop MCP de negócio dentro do agente.
## Workflow-backed tools
@@ -215,15 +193,13 @@ Quando a operação é implementada por workflow, o caminho preferencial do resu
workflow.output[tool_name].results
```
Isso permite distinguir a operação primária de etapas auxiliares. Uma falha posterior não deve apagar o sucesso terminal de itens já executados.
Uma falha posterior não deve apagar sucesso terminal de itens já executados.
## Documentação completa
Consulte também:
- `docs/MCP_MULTI_ITEM_DEVELOPER_GUIDE.md` — guia canônico em português;
- `docs/MCP_MULTI_ITEM_DEVELOPER_GUIDE_en.md` — guia canônico em inglês;
- `templates/agent_template_backend/docs/MCP_MULTI_ITEM.md` — referência junto ao template;
- `specs/SPEC-010-Agent-Development.md` — regra arquitetural de desenvolvimento.
- `specs/SPEC-010-Agent-Development.md` — regra arquitetural.
Para um passo a passo prático, leia `IMPLEMENTACAO_MULTI_ITEM_MCP.md` nesta pasta.
Para o passo a passo prático, leia `IMPLEMENTACAO_MULTI_ITEM_MCP.md`.

View File

@@ -1,69 +1,58 @@
# Multi-Item MCP
Reference capability for MCP operations that process **multiple items of the same kind** in one user intent: products, orders, services, assets, invoices, lines, contracts, or resources.
Reference capability for MCP operations that process more than one item under a single logical user intent.
This capability is **framework-native**. It does not require a multi-item engine in the agent and does not introduce new mandatory keys in `tools.yaml` or `tool_policies.yaml`.
> Multi-item support is **not enabled by `type: array`**. The input may be scalar (`subject`, `id`, `query`) or a collection. Multi-item behavior comes from resolving/executing several items and returning per-item `results[]`.
```text
Agent selects the operation; no fan-out engine
-> tools.yaml declares array/list
-> tool_policies.yaml confirmation + pre-validation
-> MCP validator resolves/canonicalizes items
-> MCP tool/workflow executes items and returns results[]
-> Agent Framework preserves per-item evidence and derives
SUCCESS / PARTIAL_SUCCESS / FAILED
-> Presentation reports each success/failure
Agent selects the operation; no business fan-out
-> tools.yaml declares the natural input contract: scalar OR collection
-> tool_policies confirmation/requires/pre-validation; no special multi-item syntax
-> validator resolves/canonicalizes and may expand one value into items[]
-> MCP/workflow executes 1 or N items and returns results[]
-> framework preserves per-item evidence and derives SUCCESS/PARTIAL_SUCCESS/FAILED
-> presentation reports each success/failure
```
## Minimal configuration
`tools.yaml` keeps the existing list contract:
```yaml
tools:
cancel_products:
requires: [items]
args_schema:
items:
type: array
```
`tool_policies.yaml` also keeps the current transaction contract:
## Scalar pattern
```yaml
tool_policies:
cancel_products:
cancelar_vas_avulso:
operation_type: transactional
require_confirmation: true
requires: [items]
requires:
- subject
pre_validation:
enabled: true
tool: validate_products_for_cancellation
tool: validar_vas_subject
fail_open: false
```
No `multi_item: true`, framework fan-out flag, or extra agent code is required.
`subject` may represent one or many entities. The validator/workflow may expand it into canonical `items[]`.
## MCP result contract
## Explicit batch pattern
The primary tool should return `results[]` with boolean `success` or `ok` per item:
```yaml
args_schema:
items:
type: array
```
This is supported, but it is **an interface option, not a requirement**.
## Result contract
```json
{
"results": [
{"name": "A", "success": true},
{"name": "B", "success": false, "error": "not_found"},
{"name": "B", "success": false},
{"name": "C", "success": true}
]
}
```
The framework derives `PARTIAL_SUCCESS` for the example above and preserves the successful items.
The runtime derives `PARTIAL_SUCCESS` and preserves the successful items.
If the downstream system only supports single-item APIs, put the fan-out inside the MCP Server or domain workflow, not inside the agent.
For the complete contract see:
- `docs/MCP_MULTI_ITEM_DEVELOPER_GUIDE_en.md`
- `docs/MCP_MULTI_ITEM_DEVELOPER_GUIDE.md`
- `IMPLEMENTACAO_MULTI_ITEM_MCP.md`
For full details, read `docs/MCP_MULTI_ITEM_DEVELOPER_GUIDE_en.md`.