Terminal AI Agents Workshop
Table of Contents
1. Overview
Rather than memorizing flags and piping outputs, developers describe intent and let agents orchestrate tool execution.
Repository: terminal-ai-agents-workshop
2. Tool Use Patterns
2.1. The Tool Abstraction
- Input schema: JSON Schema defining expected parameters
- Output format: Structured responses agents can parse
- Error handling: Predictable failure modes with actionable messages
- Idempotency: Safe to retry without side effects where possible
2.2. Common Tool Categories
| Category | Examples | Agent Considerations |
|---|---|---|
| File System | read, write, glob, grep | Path validation, permission aware |
| Process | bash, background tasks | Timeout handling, output limits |
| Version Control | git status, diff, commit | State awareness, conflict detection |
| Network | fetch, API calls | Rate limiting, caching |
| Analysis | LSP, linting, testing | Context aggregation |
2.3. Composition Patterns
- Sequential: Output of one tool feeds input of next
- Parallel: Independent tools run concurrently
- Conditional: Tool selection based on prior results
- Iterative: Repeated tool invocation until condition met
3. Model Context Protocol (MCP)
MCP standardizes how AI applications connect to external tools and data sources.
3.1. Core Concepts
Checked the current MCP specification (modelcontextprotocol.io/specification) directly: the two standard transport bindings are =stdio= and =Streamable HTTP=. "HTTP+SSE" was the pre-2025-03-26 transport name; the spec replaced it with Streamable HTTP, which was still current as of the 2026-07-28 revision.
- Servers: Expose tools, resources, and prompts
- Clients: AI applications that connect to servers
- Transports: Communication mechanisms (stdio, Streamable HTTP)
3.2. Server Implementation Pattern
from mcp.server import Server
from mcp.types import Tool, TextContent
server = Server("terminal-tools")
@server.tool()
async def run_command(command: str, timeout: int = 30) -> str:
"""Execute a shell command with timeout."""
result = await asyncio.create_subprocess_shell(
command,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE
)
stdout, stderr = await asyncio.wait_for(
result.communicate(),
timeout=timeout
)
return stdout.decode() if result.returncode == 0 else stderr.decode()
3.3. Tool Definition Best Practices
{
"name": "file_search",
"description": "Search for files matching a glob pattern",
"inputSchema": {
"type": "object",
"properties": {
"pattern": {
"type": "string",
"description": "Glob pattern (e.g., '**/*.py')"
},
"path": {
"type": "string",
"description": "Root directory to search from"
}
},
"required": ["pattern"]
}
}
4. Agent Architecture
4.1. Planning vs Execution
- Understand: Parse user intent, gather context
- Plan: Determine tool sequence, identify dependencies
- Execute: Run tools, handle errors, adapt
- Synthesize: Combine results, present to user
4.2. Context Management
- Conversation: Prior messages and decisions
- Codebase: File structure, dependencies, patterns
- Environment: Working directory, available tools
- Task: Current objective and progress
4.3. Error Recovery Strategies
| Error Type | Recovery Strategy |
|---|---|
| Tool not found | Search for alternatives, ask user |
| Permission denied | Explain limitation, suggest workaround |
| Timeout | Retry with longer timeout or decompose |
| Parse failure | Request clarification, show raw output |
| Rate limit | Backoff, queue, or switch providers |
5. Implementation Examples
5.1. Claude Code
- Persistent shell sessions with state management
- Parallel tool execution with dependency tracking
- Summarization for context window management
- Hook system for customization
5.2. Custom Agents with Agent SDK
Checked the real Claude Agent SDK (PyPI =claude-agent-sdk=, github.com/anthropics/claude-agent-sdk-python): the package is =claude_agent_sdk= (not =claude_code_sdk=), and it has no =Agent=/=Tool= classes to subclass. Tools are defined with an =@tool= decorator and registered via =create_sdk_mcp_server=; the client-side class is =ClaudeSDKClient= (configured with =ClaudeAgentOptions=), used as an async context manager rather than a base class to subclass.
from claude_agent_sdk import tool, create_sdk_mcp_server
@tool("run_bash", "Execute a shell command with sandboxing", {"command": str})
async def run_bash(args):
# Execute with sandboxing
pass
server = create_sdk_mcp_server(
name="terminal-tools",
version="1.0.0",
tools=[run_bash],
)
6. Security Considerations
- Sandboxing: Limit file system and network access
- Command validation: Prevent injection attacks
- Secrets management: Never expose credentials in logs
- Audit logging: Track all tool invocations
- Rate limiting: Prevent runaway execution
7. Related Research
- Model Context Protocol - Tool use and connector patterns
- Multi-Agent Frameworks - LangGraph, CrewAI, AutoGen
- Agentic Systems Q4 2024 - Research overview