Construindo Habilidades Personalizadas
Aprenda a projetar, implementar, testar e implantar habilidades personalizadas para agentes de IA com integracao de ferramentas.
Ciclo de Vida de Desenvolvimento
Construir uma habilidade personalizada segue um ciclo de vida estruturado do conceito a implantacao.
O ciclo de vida e iterativo. Cada implantacao fornece feedback que informa a proxima iteracao de design.
Estrutura do Manifesto
# skills/gerador-api-client/skill.yaml
name: gerador-api-client
version: "1.0.0"
description: |
Gera bibliotecas de cliente API type-safe a partir de
especificacoes OpenAPI/Swagger.
author: "Nuniversity"
license: "MIT"
instructions:
- path: instructions/gerar-cliente.md
tools:
required:
- read
- write
- glob
optional:
- bash
resources:
- path: templates/python-client.py.hbs
autoload:
enabled: true
matchPattern: "gerar cliente|api client|openapi|swagger"
constraints:
maxTokens: 8192
temperature: 0.3Declare ferramentas com precisao. Marque como required apenas se a habilidade nao funcionar sem elas. Use optional para ferramentas que melhoram resultados mas tem fallback.
Implementacao Programatica
import json
import os
class HabilidadeGeradorClienteAPI:
def __init__(self, agente):
self.agente = agente
self.handlers_idioma = {
"python": self._gerar_python,
"typescript": self._gerar_typescript,
}
async def executar(self, caminho_spec, idioma="python", dir_saida="gerado"):
conteudo = await self.agente.ler(caminho_spec)
spec = json.loads(conteudo)
erros = self._validar_spec(spec)
if erros:
return {"status": "erro", "erros_validacao": erros}
os.makedirs(dir_saida, exist_ok=True)
handler = self.handlers_idioma.get(idioma)
if not handler:
return {"status": "erro", "mensagem": f"Idioma nao suportado: {idioma}"}
codigo = handler(spec, caminho_spec)
caminho = os.path.join(dir_saida, self._nome_arquivo(idioma))
await self.agente.escrever(caminho, codigo)
return {
"status": "sucesso",
"arquivo": caminho,
"endpoints_gerados": len(spec.get("paths", {}))
}
def _validar_spec(self, spec):
erros = []
if "openapi" not in spec and "swagger" not in spec:
erros.append("Campo de versao ausente")
if "info" not in spec:
erros.append("Secao info ausente")
if "paths" not in spec or not spec["paths"]:
erros.append("Nenhum path definido")
return erros
def _gerar_python(self, spec, caminho):
nome = spec.get("info", {}).get("title", "ApiClient")
linhas = [
'"""Cliente API gerado automaticamente"""',
"import requests",
"",
f"class {nome.replace(' ', '')}Client:",
f' """Cliente para API {nome}."""',
" def __init__(self, base_url, api_key=None):",
" self.base_url = base_url.rstrip('/')",
" self.session = requests.Session()",
" if api_key:",
' self.session.headers["Authorization"] = f"Bearer {api_key}"',
"",
]
for path, methods in spec.get("paths", {}).items():
for method in methods:
func_name = self._caminho_para_funcao(method, path)
linhas.append(f" def {func_name}(self):")
linhas.append(f' url = f"{{self.base_url}}{path}"')
linhas.append(f" response = self.session.{method}(url)")
linhas.append(" response.raise_for_status()")
linhas.append(" return response.json()")
linhas.append("")
return "\n".join(linhas)
def _gerar_typescript(self, spec, caminho):
nome = spec.get("info", {}).get("title", "ApiClient")
linhas = [
f"// Cliente gerado automaticamente para {nome}",
"import axios, { AxiosInstance } from 'axios';",
"",
f"export class {nome.replace(' ', '')}Client {{",
" private client: AxiosInstance;",
" constructor(baseURL: string, apiKey?: string) {",
" this.client = axios.create({ baseURL });",
" if (apiKey) {",
" this.client.defaults.headers.common['Authorization'] = `Bearer ${apiKey}`;",
" }",
" }",
"",
]
for path, methods in spec.get("paths", {}).items():
for method in methods:
func_name = self._caminho_para_funcao(method, path)
linhas.append(f" async {func_name}(): Promise<any> {{")
linhas.append(f" const response = await this.client.{method}('{path}');")
linhas.append(" return response.data;")
linhas.append(" }")
linhas.append("")
linhas.append("}")
return "\n".join(linhas)
def _caminho_para_funcao(self, method, path):
partes = path.strip("/").replace("/", "_").replace("-", "_").replace("{", "").replace("}", "")
return f"{method}_{partes}"
def _nome_arquivo(self, idioma):
return {"python": "client.py", "typescript": "client.ts"}[idioma]Testando Habilidades
import pytest
import json
from unittest.mock import AsyncMock
@pytest.fixture
def agente_mock():
agente = AsyncMock()
agente.ler.return_value = json.dumps({
"openapi": "3.0.0",
"info": {"title": "API Teste", "version": "1.0.0"},
"paths": {
"/usuarios": {"get": {"summary": "Listar usuarios"}},
"/usuarios/{id}": {"get": {"summary": "Obter usuario"}}
}
})
return agente
@pytest.mark.asyncio
async def test_gerador_python(agente_mock):
habilidade = HabilidadeGeradorClienteAPI(agente_mock)
resultado = await habilidade.executar("spec.yaml", idioma="python")
assert resultado["status"] == "sucesso"
assert resultado["endpoints_gerados"] == 2
@pytest.mark.asyncio
async def test_gerador_typescript(agente_mock):
habilidade = HabilidadeGeradorClienteAPI(agente_mock)
resultado = await habilidade.executar("spec.yaml", idioma="typescript")
assert resultado["status"] == "sucesso"
@pytest.mark.asyncio
async def test_spec_invalida(agente_mock):
agente_mock.ler.return_value = json.dumps({"openapi": "3.0.0"})
habilidade = HabilidadeGeradorClienteAPI(agente_mock)
resultado = await habilidade.executar("invalida.yaml")
assert resultado["status"] == "erro"
assert len(resultado["erros_validacao"]) > 0
@pytest.mark.asyncio
async def test_idioma_nao_suportado(agente_mock):
habilidade = HabilidadeGeradorClienteAPI(agente_mock)
resultado = await habilidade.executar("spec.yaml", idioma="rust")
assert resultado["status"] == "erro"
assert "rust" in resultado["mensagem"].lower()Pratica
Como responder
Questão de múltipla escolha com 4 opções. Selecione uma opção e escolha Verificar resposta.
Quais sao os tres componentes obrigatorios de um manifesto de habilidade?
Como responder
Questão de múltipla escolha com 4 opções. Selecione uma opção e escolha Verificar resposta.
Quando uma ferramenta deve ser marcada como 'required' vs 'optional'?
- Habilidades seguem ciclo: Design -> Implementacao -> Testes -> Implantacao -> Monitoramento
- Manifestos declaram identidade, ferramentas, recursos e padroes de carregamento
- Instrucoes sao o nucleo; devem ser claras e tratar casos limite
- Teste com agentes mock para testes unitarios e ferramentas reais para integracao
- Evite "Habilidades Deus"; siga responsabilidade unica
- Use templates Handlebars para codigo gerado em habilidades
Fluxo de Trabalho Detalhado
Este diagrama ilustra o fluxo de trabalho basico do agente. Adapte-o ao seu caso de uso especifico.
Exemplos Adicionais de Codigo
# Exemplo adicional de implementacao
class ExemploAdicional:
"""Classe de exemplo para ilustrar conceitos adicionais."""
def __init__(self, nome):
self.nome = nome
self.dados = {}
def processar(self, entrada):
"""Processa a entrada e armazena o resultado."""
resultado = self._transformar(entrada)
self.dados[entrada] = resultado
return resultado
def _transformar(self, valor):
return valor * 2 if isinstance(valor, (int, float)) else valor.upper()
def obter_estatisticas(self):
"""Retorna estatisticas sobre os dados processados."""
if not self.dados:
return {"status": "vazio", "total": 0}
return {
"status": "processado",
"total": len(self.dados),
"ultimo": list(self.dados.keys())[-1]
}
exemplo = ExemploAdicional('teste')
print(exemplo.processar(21)) # 42
print(exemplo.obter_estatisticas()){
"configuracao_exemplo": {
"versao": "1.0",
"parametros": {
"timeout": 30,
"max_tentativas": 3,
"modo": "automatico"
},
"seguranca": {
"requer_aprovacao": true,
"nivel_autonomia": 2
}
}
}# configuracao-adicional.yaml
ambiente:
nome: producao
variaveis:
LOG_LEVEL: "debug"
MAX_TOKENS: 128000
agentes:
- nome: agente-principal
modelo: gpt-4o
temperatura: 0.3
- nome: agente-revisor
modelo: claude-sonnet-4-20250514
ferramentas_permitidas:
- read
- grep
- glob
ferramentas_negadas:
- write
- edit
- bash
monitoramento:
metrics: true
tracing: true
alertas:
- tipo: erro_critico
canal: slack
- tipo: timeout
canal: emailNotas Importantes
Este conceito e fundamental para o entendimento do modulo. Certifique-se de compreende-lo antes de prosseguir.
Preste atencao a este detalhe: configuracoes incorretas podem levar a comportamentos inesperados do agente.
Uma dica pratica: sempre valide suas configuracoes em ambiente de staging antes de promover para producao.
Ao dominar este conceito, voce estara apto a construir agentes mais robustos e confiaveis.
Tabela Comparativa
Caracteristica | Abordagem A | Abordagem B | Abordagem C |
|---|---|---|---|
Complexidade | Baixa | Media | Alta |
Flexibilidade | Limitada | Moderada | Total |
Manutencao | Facil | Media | Dificil |
Performance | Otima | Boa | Variavel |
Seguranca | Basica | Avancada | Maxima |
Caso de uso | Prototipos | Producao | Sistemas criticos |
Escolha a abordagem com base nos requisitos especificos do seu projeto. Nao existe solucao unica para todos os casos.
Como responder
Questão de múltipla escolha com 4 opções. Selecione uma opção e escolha Verificar resposta.
Pergunta adicional 1 sobre o conteudo desta aula?
Como responder
Questão de múltipla escolha com 4 opções. Selecione uma opção e escolha Verificar resposta.
Pergunta adicional 2 sobre o conteudo desta aula?
Como responder
Questão de múltipla escolha com 4 opções. Selecione uma opção e escolha Verificar resposta.
Pergunta adicional 3 sobre o conteudo desta aula?
- Reforce seu entendimento praticando com exemplos reais
- Consulte a documentacao oficial para casos avancados
- Compartilhe seu conhecimento com a comunidade
- Sempre teste suas implementacoes em ambientes controlados
- Mantenha-se atualizado com as melhores praticas da industria
- A pratica consistente e a chave para a maestria
- Agentes de IA bem projetados combinam tecnologia com boas praticas de engenharia