Creating a Custom Skill
This guide walks through creating a complete custom skill from scratch. We will build a weather skill that gives an agent the ability to check current weather conditions.
Step 1 — Create the underlying tool
Skills bundle tools, so first create the tool that the skill will expose. Create src/tools/weather-lookup.ts:
typescript
// src/tools/weather-lookup.ts
import { z } from 'zod';
import { registerTool } from './registry';
const Params = z.object({
location: z.string().describe('City name or "lat,lon" coordinates'),
units: z.enum(['celsius', 'fahrenheit']).default('celsius'),
});
registerTool({
name: 'weather_lookup',
description: 'Get current weather conditions for a location',
parameters: Params,
execute: async (params, ctx) => {
const apiKey = process.env.WEATHER_API_KEY;
if (!apiKey) {
return { error: 'WEATHER_API_KEY not configured' };
}
const url = \`https://api.openweathermap.org/data/2.5/weather?q=${encodeURIComponent(params.location)}&appid=${apiKey}&units=${params.units === 'celsius' ? 'metric' : 'imperial'}\`;
const response = await fetch(url);
if (!response.ok) {
return { error: \`Weather API error: ${response.status}\` };
}
const data = await response.json();
return {
location: data.name,
temperature: data.main.temp,
description: data.weather[0].description,
humidity: data.main.humidity,
windSpeed: data.wind.speed,
};
},
});Step 2 — Register the tool import
Add the import to src/tools/index.ts so it self-registers at startup:
typescript
// src/tools/index.ts
// ... existing imports ...
import './weather-lookup';Step 3 — Create the skill definition
Create src/skills/definitions/weather/index.ts:
typescript
// src/skills/definitions/weather/index.ts
import type { SkillDefinition } from '../../types';
const skill: SkillDefinition = {
manifest: {
id: 'weather',
displayName: 'Weather',
category: 'utilities',
description: 'Check current weather conditions for any location',
tools: ['weather_lookup'],
},
async init() {
// Validate that the API key is present and warn if missing
if (!process.env.WEATHER_API_KEY) {
console.warn('[weather skill] WEATHER_API_KEY not set — weather_lookup will return errors');
}
},
getPromptContext() {
return \`You have access to the weather_lookup tool.
Use it when the user asks about current weather, temperature, or conditions for any location.
Always specify whether you are reporting in celsius or fahrenheit.
If the user does not specify units, use celsius by default.\`;
},
};
export default skill;Step 4 — Assign the skill to an agent
yaml
agents:
- id: assistant
skills:
- weather # Add your new skill
tools:
allow:
- weather_lookupStep 5 — Verify
bash
# Type-check first
npm run typecheck
# Start the gateway (skill auto-discovered on startup)
npm run dev
# Test via CLI
npx astra chat
> What is the weather in Tokyo right now?💡If the skill does not appear in agent responses, check the gateway startup logs for
[skills] Discovered: weather. If missing, verify the file path is exactly src/skills/definitions/weather/index.ts and that the default export is a valid SkillDefinition.Standard skill categories
Use one of these established category values in your manifest to ensure correct grouping in the UI:
code— Code development and review toolsvcs— Version control toolsresearch— Web and document research toolsdata— Data analysis and transformation toolsdevops— Infrastructure and operations toolsproductivity— Project management and communication toolssecurity— Security review and audit toolsknowledge— Team knowledge and memory toolsutilities— General-purpose utilities