Communitygithub.com

SamuelChien/mega-skills-collection

Ferramentas são como agentes de IA interagem com o mundo. Uma ferramenta bem projetada é a diferença entre um agente que funciona e um que alucina, falha silenciosamente ou custa 10x mais tokens do que o necessário. Esta skill aborda design de ferramentas, do esquema ao tratamento de erros.

O que é mega-skills-collection?

Esta skill de design de ferramentas para agentes de IA foca na criação de ferramentas eficientes e confiáveis, desde o esquema até o tratamento de erros. A principal ênfase é que as descrições das ferramentas são mais importantes do que suas implementações, pois o LLM nunca vê o código, apenas o esquema e a descrição. A skill cobre práticas recomendadas de JSON Schema, como descrições detalhadas, uso de enums, parâmetros obrigatórios versus opcionais e exemplos de entrada para guiar o uso do LLM. Também aborda o padrão emergente MCP (Model Context Protocol) para criar ferramentas reutilizáveis e multiplataforma, juntamente com padrões de tratamento de erros que ajudam o LLM a se recuperar de falhas. Inclui princípios como: qualidade da descrição acima da qualidade da implementação, menos de 20 ferramentas por agente para evitar confusão, validação de entrada antes da execução e retorno de strings em vez de objetos. Suporta SDKs de provedores como Anthropic, OpenAI, Vercel AI e LangChain, e demonstra padrões como execução paralela de ferramentas e uso de tool runners automáticos.

Funciona com✓Claude Code✓Codex CLI~Cursor
npx skills add https://github.com/SamuelChien/mega-skills-collection/tree/HEAD/agent-tool-builder

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

Construtor de Ferramentas para Agentes

Ferramentas são como agentes de IA interagem com o mundo. Uma ferramenta bem projetada é a diferença entre um agente que funciona e um que alucina, falha silenciosamente ou custa 10x mais tokens do que o necessário.

Esta skill aborda design de ferramentas, do esquema ao tratamento de erros. Práticas recomendadas de JSON Schema, escrita de descrições que realmente ajudam o LLM, validação e o emergente padrão MCP que está se tornando a lingua franca para ferramentas de IA.

Insight chave: Descrições de ferramentas são mais importantes que implementações de ferramentas. O LLM nunca vê seu código - ele vê apenas o esquema e a descrição.

Princípios

  • Qualidade da descrição > qualidade da implementação para precisão do LLM
  • Mire em menos de 20 ferramentas - mais causa confusão
  • Toda ferramenta precisa de tratamento explícito de erros - falhas silenciosas envenenam agentes
  • Retorne strings, não objetos - LLMs processam texto
  • Validação antes da execução - rejeite, corrija ou escale, nunca falhe silenciosamente
  • Teste ferramentas com o LLM, não apenas testes unitários

Capacidades

  • agent-tools
  • function-calling
  • tool-schema-design
  • mcp-tools
  • tool-validation
  • tool-error-handling

Escopo

  • multi-agent-coordination → multi-agent-orchestration
  • agent-memory → agent-memory-systems
  • api-design → api-designer
  • llm-prompting → prompt-engineering

Ferramentas

Padrões

  • JSON Schema - Quando: Todas as definições de ferramenta Nota: O formato universal para esquemas de ferramenta
  • MCP (Model Context Protocol) - Quando: Construindo ferramentas reutilizáveis e multiplataforma Nota: Padrão aberto da Anthropic, amplamente adotado

Frameworks

  • Anthropic SDK - Quando: Agentes baseados em Claude Nota: O tool runner beta lida com a maioria da complexidade
  • OpenAI Functions - Quando: Agentes baseados em OpenAI Nota: Use modo estrito para conformidade garantida com o esquema
  • Vercel AI SDK - Quando: Manipulação de ferramentas de múltiplos provedores Nota: Abstrai diferenças entre provedores
  • LangChain Tools - Quando: Agentes baseados em LangChain Nota: Converte ferramentas MCP para o formato LangChain

Padrões

Design de Esquema de Ferramenta

Criando JSON Schema claro e inequívoco para ferramentas

Quando usar: Definindo qualquer nova ferramenta para um agente

PRÁTICAS RECOMENDADAS DE ESQUEMA DE FERRAMENTA:

1. Descrições Detalhadas (Mais Importante)

RUIM - Muito vago:
{
  "name": "get_stock_price",
  "description": "Obtém preço de ação",
  "input_schema": {
    "type": "object",
    "properties": {
      "ticker": {"type": "string"}
    }
  }
}

BOM - Abrangente:
{
  "name": "get_stock_price",
  "description": "Recupera o preço atual da ação para um símbolo de ticker
    fornecido. O símbolo do ticker deve ser um símbolo válido para uma empresa
    de capital aberto em uma grande bolsa de valores dos EUA como NYSE ou NASDAQ.
    Retorna o último preço de negociação em USD. Use quando o usuário perguntar
    sobre preços atuais ou recentes de ações. NÃO fornece dados
    históricos, informações da empresa ou previsões.",
  "input_schema": {
    "type": "object",
    "properties": {
      "ticker": {
        "type": "string",
        "description": "O símbolo do ticker da ação, ex: AAPL para Apple Inc."
      }
    },
    "required": ["ticker"]
  }
}

2. Descrições de Parâmetros

Todo parâmetro precisa:
- O que é
- Formato esperado
- Valor de exemplo
- Casos extremos/limitações

{
  "location": {
    "type": "string",
    "description": "Cidade e estado/país. Formato: 'Cidade, Estado' para EUA
      (ex: 'São Francisco, CA') ou 'Cidade, País' para internacional
      (ex: 'Tóquio, Japão'). Não use CEP ou coordenadas."
  },
  "unit": {
    "type": "string",
    "enum": ["celsius", "fahrenheit"],
    "description": "Unidade de temperatura. Padrão é a localidade do usuário se não
      especificado. Use 'fahrenheit' para usuários dos EUA, 'celsius' para outros."
  }
}

3. Use Enums Quando Possível

Enums restringem o LLM a valores válidos:

"priority": {
  "type": "string",
  "enum": ["baixa", "média", "alta", "crítica"],
  "description": "Nível de prioridade da tarefa"
}

"action": {
  "type": "string",
  "enum": ["criar", "ler", "atualizar", "excluir"],
  "description": "A operação CRUD a ser executada"
}

4. Obrigatório vs Opcional

Seja explícito sobre o que é obrigatório:

{
  "type": "object",
  "properties": {
    "query": {...},      // Obrigatório
    "limit": {...},      // Opcional com padrão
    "offset": {...}      // Opcional
  },
  "required": ["query"],
  "additionalProperties": false  // Modo estrito
}

Ferramenta com Exemplos de Entrada

Usando exemplos para guiar o uso da ferramenta pelo LLM

Quando usar: Ferramentas complexas com objetos aninhados ou entradas sensíveis a formato

EXEMPLOS DE USO DA FERRAMENTA (Recurso Beta Anthropic):

Exemplos mostram a Claude padrões concretos que esquemas não conseguem expressar.
Melhora a precisão de 72% para 90% em operações complexas.

{ "name": "criar_evento_calendario", "description": "Cria um evento de calendário com participantes e lembretes opcionais", "input_schema": { "type": "object", "properties": { "title": {"type": "string", "description": "Título do evento"}, "start_time": { "type": "string", "description": "Data e hora no formato ISO 8601, ex: 2024-03-15T14:00:00Z" }, "duration_minutes": {"type": "integer", "description": "Duração do evento"}, "attendees": { "type": "array", "items": {"type": "string"}, "description": "Endereços de email dos participantes" } }, "required": ["title", "start_time", "duration_minutes"] }, "input_examples": [ { "title": "Reunião de Equipe", "start_time": "2024-03-15T09:00:00Z", "duration_minutes": 30, "attendees": ["[email protected]", "[email protected]"] }, { "title": "Bate-papo Rápido", "start_time": "2024-03-15T14:00:00Z", "duration_minutes": 15 }, { "title": "Revisão de Projeto", "start_time": "2024-03-15T16:00:00-05:00", "duration_minutes": 60, "attendees": ["[email protected]"] } ] }

PRINCÍPIOS DE DESIGN DE EXEMPLOS:

- Use dados realistas, não placeholders

- Mostre padrões de especificação mínima, parcial e completa

- Mantenha conciso: 1-5 exemplos por ferramenta

- Foque em casos ambíguos

Tratamento de Erros da Ferramenta

Retornando erros que ajudam o LLM a se recuperar

Quando usar: Qualquer ferramenta que pode falhar

PRÁTICAS RECOMENDADAS DE TRATAMENTO DE ERROS:

Retorne Erros Informativos

RUIM:
{"error": "Falhou"}
{"error": true}

BOM:
{
  "error": true,
  "error_type": "nao_encontrado",
  "message": "Local 'Atlântida' não encontrado no banco de dados meteorológico.
    Forneça um nome de cidade real como 'São Francisco, CA'.",
  "suggestions": ["São Francisco, CA", "Los Angeles, CA"]
}

Resultado de Ferramenta Anthropic com Erro

{
  "type": "tool_result",
  "tool_use_id": "toolu_01A09q90qw90lq917835lq9",
  "content": "Erro: Local 'Atlântida' não encontrado no banco de dados meteorológico.
    Forneça um nome de cidade real como 'São Francisco, CA'.",
  "is_error": true
}

Categorias de Erro para Tratar

1. Erros de Validação de Entrada
   - Parâmetros obrigatórios ausentes
   - Formato inválido
   - Valores fora do intervalo

2. Erros de Serviço Externo
   - API indisponível
   - Limite de taxa excedido
   - Tempo limite excedido

3. Erros de Lógica de Negócio
   - Recurso não encontrado
   - Permissão negada
   - Conflito/duplicata

4. Erros Internos
   - Exceções inesperadas
   - Corrupção de dados

Padrão de Implementação

from dataclasses import dataclass
from typing import Union

@dataclass
class ToolResult:
    success: bool
    content: str
    error_type: str = None
    suggestions: list[str] = None

    def to_response(self) -> dict:
        if self.success:
            return {"content": self.content}
        return {
            "content": f"Erro ({self.error_type}): {self.content}",
            "is_error": True
        }

def get_weather(location: str) -> ToolResult:
    # Validar entrada
    if not location or len(location) < 2:
        return ToolResult(
            success=False,
            content="Local deve ter pelo menos 2 caracteres",
            error_type="validation_error"
        )

    try:
        data = weather_api.fetch(location)
        return ToolResult(
            success=True,
            content=f"Temperatura: {data.temp}°F, Condições: {data.conditions}"
        )
    except LocationNotFound:
        return ToolResult(
            success=False,
            content=f"Local '{location}' não encontrado",
            error_type="not_found",
            suggestions=weather_api.suggest_locations(location)
        )
    except RateLimitError:
        return ToolResult(
            success=False,
            content="Limite de taxa do serviço meteorológico excedido. Tente novamente em 60 segundos.",
            error_type="rate_limit"
        )
    except Exception as e:
        return ToolResult(
            success=False,
            content=f"Erro inesperado: {str(e)}",
            error_type="internal_error"
        )

Padrão de Ferramenta MCP

Construindo ferramentas usando Model Context Protocol

Quando usar: Criando ferramentas reutilizáveis e multiplataforma

IMPLEMENTAÇÃO DE FERRAMENTA MCP:

MCP (Model Context Protocol) é o padrão aberto da Anthropic para
conectar agentes de IA a sistemas externos. Construa uma vez, use em toda parte.

Servidor MCP Básico (TypeScript)

import { Server } from "@modelcontextprotocol/sdk/server";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio";

const server = new Server({
  name: "weather-server",
  version: "1.0.0"
});

// Definir ferramentas
server.setRequestHandler("tools/list", async () => ({
  tools: [
    {
      name: "get_weather",
      description: "Obter clima atual para um local. Retorna
        temperatura, condições e umidade. Use para consultas
        meteorológicas sobre cidades específicas.",
      inputSchema: {
        type: "object",
        properties: {
          location: {
            type: "string",
            description: "Cidade e estado, ex: 'São Francisco, CA'"
          },
          unit: {
            type: "string",
            enum: ["celsius", "fahrenheit"],
            default: "fahrenheit"
          }
        },
        required: ["location"]
      }
    }
  ]
}));

// Lidar com chamadas de ferramenta
server.setRequestHandler("tools/call", async (request) => {
  const { name, arguments: args } = request.params;

  if (name === "get_weather") {
    try {
      const weather = await fetchWeather(args.location, args.unit);
      return {
        content: [
          {
            type: "text",
            text: JSON.stringify(weather)
          }
        ]
      };
    } catch (error) {
      return {
        content: [
          {
            type: "text",
            text: `Erro: ${error.message}`
          }
        ],
        isError: true
      };
    }
  }

  throw new Error(`Ferramenta desconhecida: ${name}`);
});

// Iniciar servidor
const transport = new StdioServerTransport();
await server.connect(transport);

Benefícios do MCP

- Compatibilidade universal entre provedores de LLM
- Bibliotecas de ferramentas reutilizáveis
- Suporte a transporte streaming e SSE
- Observabilidade integrada
- Controles de acesso a ferramentas

Padrão Tool Runner

Usando tool runners de SDK para manipulação automática

Quando usar: Construindo loops de ferramenta sem gerenciamento manual

TOOL RUNNER (SDK Anthropic Beta):

O tool runner lida automaticamente com o loop de chamada de ferramenta:
- Executa ferramentas quando Claude as chama
- Gerencia o estado da conversa
- Lida com tentativas de erro
- Fornece suporte a streaming

Exemplo Python

import anthropic
from anthropic import beta_tool

client = anthropic.Anthropic()

@beta_tool
def get_weather(location: str, unit: str = "fahrenheit") -> str:
    '''Obter o clima atual em um determinado local.

    Args:
        location: A cidade e estado, ex: São Francisco, CA
        unit: Unidade de temperatura, 'celsius' ou 'fahrenheit'
    '''
    # Implementação
    return json.dumps({"temperature": "72°F", "conditions": "Ensolarado"})

@beta_tool
def search_web(query: str) -> str:
    '''Pesquisar na web por informações.

    Args:
        query: A consulta de pesquisa
    '''
    # Implementação
    return json.dumps({"results": [...]})

# Tool runner lida com o loop
runner = client.beta.messages.tool_runner(
    model="claude-sonnet-4-5",
    max_tokens=1024,
    tools=[get_weather, search_web],
    messages=[
        {"role": "user", "content": "Como está o clima em Paris?"}
    ]
)

# Processar cada mensagem
for message in runner:
    print(message.content[0].text)

# Ou apenas obter o resultado final
final = runner.until_done()

TypeScript com Zod

import { Anthropic } from '@anthropic-ai/sdk';
import { betaZodTool } from '@anthropic-ai/sdk/helpers/beta/zod';
import { z } from 'zod';

const anthropic = new Anthropic();

const getWeatherTool = betaZodTool({
  name: 'get_weather',
  description: 'Obter o clima atual em um determinado local',
  inputSchema: z.object({
    location: z.string().describe('Cidade e estado, ex: São Francisco, CA'),
    unit: z.enum(['celsius', 'fahrenheit']).default('fahrenheit')
  }),
  run: async (input) => {
    // Entrada com segurança de tipos!
    return JSON.stringify({temperature: '72°F'});
  }
});

const runner = anthropic.beta.messages.toolRunner({
  model: 'claude-sonnet-4-5',
  max_tokens: 1024,
  tools: [getWeatherTool],
  messages: [{ role: 'user', content: "Como está o clima em Paris?" }]
});

for await (const message of runner) {
  console.log(message.content[0].text);
}

Execução Paralela de Ferramentas

Executando múltiplas ferramentas simultaneamente

Quando usar: Chamadas de ferramenta independentes que podem ser executadas em paralelo

EXECUÇÃO PARALELA DE FERRAMENTAS:

Por padrão, Claude pode chamar múltiplas ferramentas em uma resposta.
Isso reduz drasticamente a latência para operações independentes.

Lidando com Resultados Paralelos

# Claude retorna múltiplos blocos tool_use:
response.content = [
    {"type": "text", "text": "Vou verificar ambos os locais..."},
    {"type": "tool_use", "id": "toolu_01", "name": "get_weather",
     "input": {"location": "San Francisco, CA"}},
    {"type": "tool_use", "id": "toolu_02", "name": "get_weather",
     "input": {"location": "New York, NY"}},
    {"type": "tool_use", "id": "toolu_03", "name": "get_time",
     "input": {"timezone": "America/Los_Angeles"}},
    {"type": "tool_use", "id": "toolu_04", "name": "get_time",
     "input": {"timezone": "America/New_York"}}
]

Padrão de Execução Paralela em Python

from concurrent.futures import ThreadPoolExecutor
from typing import List, Dict

def execute_tools_parallel(tools_responses: List[Dict]) -> List[str]:
    """Executa ferramentas em paralelo com base em respostas da API."""
    results = [None] * len(tools_responses)

    def execute_tool(index: int, tool_call: Dict):
        tool_name = tool_call["name"]
        tool_input = tool_call["input"]

        if tool_name == "get_weather":
            results[index] = get_weather(**tool_input)
        elif tool_name == "get_time":
            results[index] = get_time(**tool_input)

    with ThreadPoolExecutor(max_workers=5) as executor:
        futures = [
            executor.submit(execute_tool, i, tc)
            for i, tc in enumerate(tools_responses)
        ]

    return results

# Exemplo de uso
parallel_results = execute_tools_parallel(tool_calls)

TypeScript com Promise.all

interface ToolCall {
  id: string;
  name: string;
  input: Record<string, any>;
}

async function executeToolsParallel(
  toolCalls: ToolCall[]
): Promise<string[]> {
  const handlers: Record<string, (input: any) => Promise<string>> = {
    get_weather: async (input) => {
      const { location, unit } = input;
      return JSON.stringify({temperature: '72°F'});
    },
    get_time: async (input) => {
      const { timezone } = input;
      return new Date().toLocaleTimeString('pt-BR', { timeZone: timezone });
    }
  };

  const results = await Promise.all(
    toolCalls.map(async (call) => {
      try {
        const handler = handlers[call.name];
        if (!handler) {
          throw new Error(`Ferramenta desconhecida: ${call.name}`);
        }
        return await handler(call.input);
      } catch (error) {
        return JSON.stringify({
          error: true,
          message: `Erro executando ${call.name}: ${error.message}`
        });
      }
    })
  );

  return results;
}

// Exemplo de uso
const toolCalls: ToolCall[] = [
  { id: 'toolu_01', name: 'get_weather', input: { location: 'São Francisco, CA' } },
  { id: 'toolu_02', name: 'get_time', input: { timezone: 'America/Los_Angeles' } }
];

const results = await executeToolsParallel(toolCalls);

Padrão de Encadeamento de Ferramentas

Quando ferramentas dependem dos resultados de outras ferramentas

Quando usar: Ferramentas com dependências sequenciais

ENCADEAMENTO DE FERRAMENTAS:

Claude lida com encadeamento naturalmente - quando uma ferramenta retorna
um resultado, Claude pode decidir qual ferramenta chamar em seguida.
Isso forma uma cadeia de chamadas de ferramenta.

Exemplo de Encadeamento

def search_company(name: str) -> str:
    # Retorna informações da empresa
    return json.dumps({"symbol": "AAPL", "name": "Apple Inc.", "sector": "Tecnologia"})

def get_stock_price(symbol: str) -> str:
    # Usa o símbolo da saída de search_company
    return json.dumps({"symbol": symbol, "price": 150.25, "currency": "USD"})

def convert_currency(amount: float, from_currency: str, to_currency: str) -> str:
    # Converte o preço da ação para outra moeda
    return json.dumps({
        "original": {"amount": amount, "currency": from_currency},
        "converted": {"amount": amount * 0.92, "currency": to_currency}
    })

Lidando com Encadeamento

# Claude decide a sequência:
# 1. search_company("Apple")
# 2. get_stock_price("AAPL")
# 3. convert_currency(150.25, "USD", "EUR")

messages = [
    {"role": "user", "content": "Quanto vale uma ação da Apple em euros?"}
]

# Cada chamada de ferramenta é automaticamente encadeada
# Claude interpreta resultados e decide a próxima ação

Considerações sobre Encadeamento

- Encadeamento aumenta latência (mais viagens de ida e volta)
- Ferramentas com efeitos colaterais precisam ser idempotentes
- Cada link na cadeia é uma oportunidade para o LLM alucinar
- Mantenha cadeias curtas (2-3 ferramentas) para confiabilidade

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

SamuelChien/mega-skills-collection

Security audit, hardening, threat modeling (STRIDE/PASTA), Red/Blue Team, OWASP checks, code review, incident response, and infrastructure security for any project.

SamuelChien/mega-skills-collection

Arquitecto de Soluciones Principal y Consultor Tecnológico de Andru.ia. Diagnostica y traza la hoja de ruta óptima para proyectos de IA en español.

SamuelChien/mega-skills-collection

Ingeniero de Sistemas de Andru.ia. Diseña, redacta y despliega nuevas habilidades (skills) dentro del repositorio siguiendo el Estándar de Diamante.

SamuelChien/mega-skills-collection

Estratega de Inteligencia de Dominio de Andru.ia. Analiza el nicho específico de un proyecto para inyectar conocimientos, regulaciones y estándares únicos del sector. Actívalo tras definir el nicho.

SamuelChien/mega-skills-collection

2D game development principles. Sprites, tilemaps, physics, camera.

SamuelChien/mega-skills-collection

3D game development principles. Rendering, shaders, physics, cameras.

SamuelChien/mega-skills-collection

Expert in building 3D experiences for the web - Three.js, React Three Fiber, Spline, WebGL, and interactive 3D scenes. Covers product configurators, 3D portfolios, immersive websites, and bringing depth to web experiences.

SamuelChien/mega-skills-collection

Accessibility audit skill for scanning, fixing, and verifying WCAG 2.2 Level A and AA compliance across React, Next.js, Vue, Angular, Svelte, and plain HTML codebases. Use when auditing accessibility, fixing a11y violations, checking color contrast, generating compliance reports, or integrating accessibility checks into CI/CD pipelines.

SamuelChien/mega-skills-collection

Ab Test Analyzer - Auto-activating skill for Data Analytics. Triggers on: ab test analyzer, ab test analyzer Part of the Data Analytics skill category.

SamuelChien/mega-skills-collection

A B Test Config Creator - Auto-activating skill for ML Deployment. Triggers on: a b test config creator, a b test config creator Part of the ML Deployment skill category.

SamuelChien/mega-skills-collection

When the user wants to plan, design, or implement an A/B test or experiment. Also use when the user mentions "A/B test," "split test," "experiment," "test this change," "variant copy," "multivariate test," "hypothesis," "conversion experiment," "statistical significance," or "test this." For tracking implementation, see analytics-tracking.

SamuelChien/mega-skills-collection

Acceptance Criteria Creator - Auto-activating skill for Enterprise Workflows. Triggers on: acceptance criteria creator, acceptance criteria creator Part of the Enterprise Workflows skill category.

SamuelChien/mega-skills-collection

Use when a coding task should be driven end-to-end from issue intake through implementation, review, deployment, and acceptance verification with minimal human re-intervention.

SamuelChien/mega-skills-collection

Accessibility Audit Runner - Auto-activating skill for Frontend Development. Triggers on: accessibility audit runner, accessibility audit runner Part of the Frontend Development skill category.

SamuelChien/mega-skills-collection

You are an accessibility expert specializing in WCAG compliance, inclusive design, and assistive technology compatibility. Conduct audits, identify barriers, and provide remediation guidance.

SamuelChien/mega-skills-collection

Web accessibility patterns for WCAG 2.2 compliance including ARIA, keyboard navigation, screen readers, and testing

SamuelChien/mega-skills-collection

Manage Discord channel access — approve pairings, edit allowlists, set DM/group policy. Use when the user asks to pair, approve someone, check who's allowed, or change policy for the Discord channel.

SamuelChien/mega-skills-collection

Create unified specification packages across Business, Development, and Design teams. Staged elaboration (L0 Vision → L1 Requirements → L2 Team Detail → L3 Acceptance Criteria) to build shared understanding. Does not write code.

SamuelChien/mega-skills-collection

Research a company or person and get actionable sales intel. Works standalone with web search, supercharged when you connect enrichment tools or your CRM. Trigger with "research [company]", "look up [person]", "intel on [prospect]", "who is [name] at [company]", or "tell me about [company]".

SamuelChien/mega-skills-collection

Validate messaging consistency across website, GitHub repos, and local documentation generating read-only discrepancy reports. Use when checking content alignment or finding mixed messaging. Trigger with phrases like "check consistency", "validate documentation", or "audit messaging".

Habilidades Relacionadas