Factor 4: Tools are Structured Outputs
Principle: Tools are JSON outputs that trigger deterministic code. Clean separation between LLM decisions and code execution.
How Vel Implements This
Vel treats tool calls as structured outputs with validation:
# Tools are structured outputs with JSON schemas
tool = ToolSpec(
name='create_deployment',
input_schema={
'type': 'object',
'properties': {
'environment': {'type': 'string', 'enum': ['dev', 'staging', 'prod']},
'version': {'type': 'string'}
},
'required': ['environment', 'version']
},
output_schema={
'type': 'object',
'properties': {
'deployment_id': {'type': 'string'},
'status': {'type': 'string'}
},
'required': ['deployment_id', 'status']
},
handler=create_deployment_handler
)
# LLM decides "what", your code controls "how"
async def create_deployment_handler(input: dict, ctx: dict) -> dict:
# Your deterministic code
environment = input['environment']
version = input['version']
# Complex business logic
if environment == 'prod':
# Send to approval queue
approval_id = await request_approval(environment, version)
return {'deployment_id': approval_id, 'status': 'pending_approval'}
else:
# Direct deployment
deployment_id = await deploy(environment, version)
return {'deployment_id': deployment_id, 'status': 'deployed'}
Benefits
- ✓ LLM outputs structured JSON
- ✓ Your code executes deterministically
- ✓ Validation at input and output boundaries
- ✓ Tool execution not limited to atomic functions
See: Tools Documentation