In AI agent development, two key concepts work together to enable agents to perform useful tasks: capabilities and tools.
Capabilities
Capabilities represent what your agent can do — the specific functions or skills it possesses. As a developer, you define these capabilities as functions in your code that perform specific tasks within your domain expertise.
Tools
Tools are the bridge between natural language and your code. When Armağan discusses tools, he references a concept pioneered by OpenAI about 1.5-2 years ago. The innovation allows large language models (LLMs) to call functions non-deterministically.
As Armağan explains:
"Tools has been a huge revelation started by OpenAI...where the large language model can call a function non-deterministically. The large language model defines the parameters or the values of the parameters of the function. You give it a function signature...and the large language model magically knows how to call your function with the right parameters in the right order, in the right shape."
The Relationship Between Capabilities and Tools
On the OpenServ platform, this relationship is straightforward:
You define capabilities in your agent code
OpenServ transforms these capabilities into tools that LLMs can use
When a user makes a request, the LLM determines which tool to use
The platform calls your capability function with the structured parameters
This is what Armağan refers to as "inversion of control" — rather than your code calling the AI, the AI calls your code when it determines your capability is needed.
Why This Matters for Developers
The power of this approach is that you don't need to build the intelligence layer that:
Understands user requests
Breaks down complex tasks
Determines when to use which functions
Instead, you focus solely on implementing the specific functionality you're expert in. Your function could be as simple as calling a weather API or as complex as generating a 3D model — you decide the complexity.
Code Examples
import { Agent } from '@openserv-labs/sdk'
import { z } from 'zod'
import axios from 'axios'
// Create a new agent
const dexScreenerAnalyticsAgent = new Agent({
systemPrompt: 'You are a helpful assistant that provides up to date information about tokens.'
})
// Add a capability to the agent
dexScreenerAnalyticsAgent.addCapability({
name: 'filterTokens',
description: 'Filter tokens by specific criteria',
schema: z.object({
chain: z.string().optional().describe('Filter tokens by blockchain (e.g., "solana", "ethereum", "bsc")'),
minVolume24h: z.number().optional().describe('Minimum 24-hour trading volume in USD'),
minLiquidity: z.number().optional().describe('Minimum liquidity in USD'),
minMarketCap: z.number().optional().describe('Minimum market capitalization in USD'),
maxMarketCap: z.number().optional().describe('Maximum market capitalization in USD'),
maxAgeDays: z.number().optional().describe('Maximum age of the token pair in days')
}),
async run({ args }) {
try {
// Implementation of the token filtering capability
// This is where you put your domain expertise
const response = await axios.get('https://api.dexscreener.com/token-boosts/top/v1')
// Processing logic...
return JSON.stringify(validTokens, null, 2)
} catch (error) {
console.error('Error filtering tokens:', error)
return 'Error filtering tokens. Please try again later.'
}
}
})
from openserv-sdk import Agent, AgentOptions
from openserv-sdk.capability import Capability
from pydantic import BaseModel
# Define parameter schemas with Pydantic
class SocialMediaPostParams(BaseModel):
platform: str
topic: str
class EngagementMetrics(BaseModel):
likes: int
shares: int
comments: int
impressions: int
class AnalyzeEngagementParams(BaseModel):
platform: str
metrics: EngagementMetrics
# Define capability functions
async def create_social_media_post(params: SocialMediaPostParams, messages: List[Dict[str, str]]) -> str:
"""Creates a social media post for the specified platform."""
platform = params.platform
topic = params.topic
# Implementation details...
return completion.choices[0].message.content
async def analyze_engagement(agent: Agent, params: Dict[str, Any]) -> str:
"""Analyze social media engagement metrics."""
args = params.get('args')
if not isinstance(args, AnalyzeEngagementParams):
args = AnalyzeEngagementParams.model_validate(args)
# Implementation details...
return analysis
# Create and configure the agent
marketing_manager = Agent(
AgentOptions(
system_prompt=system_prompt_path.read_text(),
api_key=os.getenv('OPENSERV_API_KEY'),
openai_api_key=os.getenv('OPENAI_API_KEY')
)
)
# Add capabilities to the agent
marketing_manager.add_capabilities([
Capability(
name='createSocialMediaPost',
description='Creates a social media post for the specified platform',
schema=SocialMediaPostParams,
run=create_social_media_post
),
Capability(
name='analyzeEngagement',
description='Analyzes social media engagement metrics and provides recommendations',
schema=AnalyzeEngagementParams,
run=analyze_engagement
)
])
The capability/tool model makes AI agent development accessible by letting you focus on your domain expertise. You define what your agent can do through capabilities, and OpenServ handles translating user requests into structured parameters that your functions can work with.
As Armağan emphasizes, "If you ever built a function in your life as an engineer and you worked with parameters and returned a response, that is basically all you need to know to get started as an AI agent developer on the OpenServ platform."
Armağan Amcalar, OpenServ CTO, breaks down the critical concepts of tools and capabilities in AI agent development.