A3S Docs
A3S CodeExamples

Direct Tools

Run deterministic host tools without spending an LLM turn

Direct Tools

session.tool(name, args) (and the typed helpers like glob, grep, readFile) run a host tool directly, with no model call in the loop. Use them for tests, migrations, and host-driven workflows where you want deterministic results instead of an agent turn. For unattended calls, set the permission policy's defaultDecision to allow so the tools don't block on a confirmation prompt.

import { Agent } from '@a3s-lab/code';

const agent = await Agent.create('agent.acl');
const session = agent.session('.', {
  permissionPolicy: { defaultDecision: 'allow' },
});

// Glob: list files by pattern
const files = await session.glob('**/*.ts');
console.log(`glob found ${files.length} TypeScript files`);

// Grep: search file contents
const matches = await session.grep('Agent.create');
console.log(`grep found ${matches.length} matches`);

// Read a file
const readme = await session.readFile('README.md');
console.log(`README is ${readme.length} bytes`);

// Direct tool call by name
const raw = await session.tool('read', { file_path: 'package.json' });
console.log(`package.json via tool(): ${String(raw).length} bytes`);

// Inspect available tool schemas
const schemas = session.toolDefinitions();
console.log(`session exposes ${schemas.length} tools`);

// Structured output: generate a schema-validated JSON object
const structured = await session.tool('generate_object', {
  schema: {
    type: 'object',
    required: ['count', 'language'],
    properties: {
      count: { type: 'integer' },
      language: { type: 'string' },
    },
  },
  prompt: 'How many TypeScript files are in this project?',
  schema_name: 'file_stats',
});
console.log('structured output:', structured);

await session.close();
from a3s_code import Agent, SessionOptions, PermissionPolicy

agent = Agent.create(open('agent.acl').read())
opts = SessionOptions()
opts.permission_policy = PermissionPolicy(default_decision='allow')
session = agent.session('.', opts)

# Glob: list files by pattern
files = session.glob('**/*.py')
print(f'glob found {len(files)} Python files')

# Grep: search file contents
matches = session.grep('Agent.create')
print(f'grep found {len(matches)} matches')

# Read a file
readme = session.read_file('README.md')
print(f'README is {len(readme)} bytes')

# Direct tool call by name
raw = session.tool('read', {'file_path': 'pyproject.toml'})
print(f'pyproject.toml via tool(): {len(str(raw))} bytes')

# Inspect available tool schemas
schemas = session.tool_definitions()
print(f'session exposes {len(schemas)} tools')

# Structured output: generate a schema-validated JSON object
structured = session.tool('generate_object', {
    'schema': {
        'type': 'object',
        'required': ['count', 'language'],
        'properties': {
            'count': {'type': 'integer'},
            'language': {'type': 'string'},
        },
    },
    'prompt': 'How many Python files are in this project?',
    'schema_name': 'file_stats',
})
print('structured output:', structured)

session.close()

Direct tools execute under the session workspace and should be treated as privileged host operations. Most calls (read, glob, grep) are purely deterministic; generate_object is the exception — it still calls the model to fill a schema-validated JSON object, but you drive it explicitly rather than through a free-form agent turn.

A runnable version ships at crates/code/sdk/node/examples/basic/test_generate_object.ts (Python: crates/code/sdk/python/examples/test_generate_object.py).

On this page