Building Blocks
Skills
Deterministic functions for business logic, integrations, and data processing
Deterministic functions for business logic that need the same infrastructure as reasoners -- without the AI.
This separation matters in production. When something breaks, you want to know whether the failure came from AI judgment or deterministic code. Skills are where you put systems-of-record access, calculations, API calls, and repeatable side effects.
from agentfield import Agent
from pydantic import BaseModel
app = Agent(node_id="inventory-service", version="1.0.0")
class StockQuery(BaseModel):
sku: str
warehouse: str = "us-east"
@app.skill(tags=["database", "inventory"])
async def check_stock(query: StockQuery) -> dict:
"""Fetch deterministic inventory state."""
row = await db.execute(
"SELECT sku, qty, reserved FROM stock WHERE sku = $1 AND warehouse = $2",
query.sku, query.warehouse,
)
if not row:
return {"sku": query.sku, "available": 0, "status": "not_found"}
available = row["qty"] - row["reserved"]
return {"sku": query.sku, "available": available, "status": "in_stock" if available > 0 else "out_of_stock"}
@app.skill(tags=["integrations", "shipping", "policy"])
async def fulfillable_quote(sku: str, dest: str, weight_kg: float) -> dict:
stock = await check_stock(StockQuery(sku=sku))
if stock["available"] <= 0:
return {"sku": sku, "fulfillable": False, "reason": "out_of_stock"}
rates = await fedex_client.rate_quote(origin="us-east", dest=dest, weight=weight_kg)
return {"sku": sku, "fulfillable": True, "rates": rates, "currency": "USD"}
app.run()
# → POST /skills/check_stock — auto-generated REST endpoint with input validation
# → POST /skills/fulfillable_quote — discoverable by any agent in the fleetimport { Agent } from '@agentfield/sdk';
const agent = new Agent({ nodeId: 'inventory-service', version: '1.0.0' });
agent.skill('check_stock', async (ctx) => {
const { sku, warehouse = 'us-east' } = ctx.input;
const row = await db.query('SELECT sku, qty, reserved FROM stock WHERE sku = $1 AND warehouse = $2', [sku, warehouse]);
if (!row) return { sku, available: 0, status: 'not_found' };
const available = row.qty - row.reserved;
return { sku, available, status: available > 0 ? 'in_stock' : 'out_of_stock' };
}, {
tags: ['database', 'inventory'],
description: 'Query real-time inventory by SKU and warehouse',
});
agent.skill('fulfillableQuote', async (ctx) => {
const stock = await agent.call('inventory-service.check_stock', {
sku: ctx.input.sku,
warehouse: 'us-east',
});
if (stock.available <= 0) {
return { sku: ctx.input.sku, fulfillable: false, reason: 'out_of_stock' };
}
const rates = await fedexClient.rateQuote({
origin: 'us-east',
dest: ctx.input.dest,
weight: ctx.input.weightKg,
});
return { sku: ctx.input.sku, fulfillable: true, rates, currency: 'USD' };
}, {
tags: ['integrations', 'shipping', 'policy'],
description: 'Check fulfillment viability and return shipping options',
});
agent.serve();
// → POST /skills/check_stock — auto-generated REST endpoint with input validation
// → POST /skills/fulfillableQuote — discoverable by any agent in the fleet// The Go SDK does not have a separate skill registration method.
// Use RegisterReasoner for all functions, whether AI-powered or deterministic.
// This registers /reasoners/check_stock, not /skills/check_stock.
a.RegisterReasoner("check_stock", func(ctx context.Context, input map[string]any) (any, error) {
sku, _ := input["sku"].(string)
warehouse, _ := input["warehouse"].(string)
if warehouse == "" {
warehouse = "us-east"
}
row, err := db.QueryRow(ctx, "SELECT qty, reserved FROM stock WHERE sku = $1 AND warehouse = $2", sku, warehouse)
if err != nil {
return map[string]any{"sku": sku, "available": 0, "status": "not_found"}, nil
}
available := row.Qty - row.Reserved
status := "out_of_stock"
if available > 0 {
status = "in_stock"
}
return map[string]any{"sku": sku, "available": available, "status": status}, nil
},
agent.WithDescription("Query real-time inventory by SKU and warehouse"),
agent.WithReasonerTags("database", "inventory"),
)What just happened
- Skills handled deterministic state and policy logic without any model call
- The second skill composed the first skill into a production-shaped workflow
- Both skills inherited the same endpoint generation, discoverability, and execution tracking as reasoners
- In Go, the same deterministic pattern is registered with
RegisterReasonerand exposed under/reasoners/{name}instead of/skills/{name}
Example proof:
Python/TypeScript:
POST /skills/check_stock
POST /skills/fulfillable_quote
discoverable target: inventory-service.fulfillable_quote
Go:
POST /reasoners/check_stock