Skip to content
skantusPublic

About

AgentLab is a project built in Typescript focused on understanding how AI agents work internally, exploring task planning, prompt engineering, structured outputs, tool calling, conversation memory, and local language models.

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

5 Commits

Folders and files

Repository files navigation

AgentLab

A local AI agent built with TypeScript, Ollama, and Qwen 3.5 9B.

AgentLab is a learning project focused on understanding how AI agents work internally, exploring task planning, prompt engineering, structured outputs, tool calling, conversation memory, and local language models.

Instead of relying on a high-level agent framework, AgentLab implements its core orchestration logic from scratch using TypeScript.

User's flow:

Table of Contents

Features

  • Local LLM inference: Runs with Ollama and Qwen 3.5 9B.
  • Task planning: Generates structured plans containing a goal, execution steps, and a decision about tool usage.
  • Tool selection: Determines whether a registered tool should be executed.
  • Controlled tool execution: Executes tools through explicit TypeScript implementations.
  • Conversation memory: Maintains message history during an interactive session.
  • Structured outputs: Uses JSON schemas and Zod to validate model-generated plans and tool decisions.
  • Interactive CLI: Provides a terminal interface for conversations.
  • Automated testing: Includes unit tests and integration tests against the local model.

Architecture

AgentLab separates LLM reasoning from application logic and tool execution.

flowchart TD
    User([User])
    CLI["index.ts<br/>Interactive CLI"]
    Session["agentSession.ts<br/>Conversation Memory"]
    Runner["runToolAgent.ts<br/>Agent Orchestrator"]

    Planner["agent.ts<br/>Task Planner"]
    Selector["toolAgent.ts<br/>Tool Selection"]
    Registry["tools.ts<br/>Tool Registry and Execution"]
    LLM["llm.ts<br/>Ollama Client"]
    Model["Qwen 3.5 9B<br/>Local LLM"]

    User --> CLI
    CLI --> Session
    Session --> Runner

    Runner --> Planner
    Runner --> Selector
    Selector --> Registry
    Planner --> LLM
    Selector --> LLM
    Runner --> Registry
    Runner --> LLM

    LLM <--> Model

    Runner --> Session
    Session --> CLI
    CLI --> User
Loading

Component Responsibilities

Component Responsibility
index.ts Reads user input and displays responses in the terminal.
agentSession.ts Maintains conversation history and supports resetting the session.
runToolAgent.ts Coordinates planning, tool execution, and final response generation.
agent.ts Generates and validates a structured task plan.
toolAgent.ts Selects a registered tool or decides that no tool is needed.
tools.ts Defines available tools and executes their implementations.
llm.ts Sends chat requests to the local Ollama API.
models.ts Defines Zod schemas and TypeScript types for structured outputs.

Execution Flow

When a user submits a request, AgentLab follows this sequence:

sequenceDiagram
    actor User
    participant CLI as index.ts
    participant Session as AgentSession
    participant Runner as runToolAgent
    participant Planner as createPlan
    participant Selector as proposeToolCall
    participant Tools as Tool Registry
    participant LLM as Ollama / Qwen

    User->>CLI: Submit a request
    CLI->>Session: send(task)
    Session->>Runner: runToolAgent(task, history)

    Runner->>Planner: Create a plan
    Planner->>LLM: Generate structured plan
    LLM-->>Planner: Plan JSON
    Planner-->>Runner: Validated AgentPlan

    opt Plan requires tools
        Runner->>Selector: Propose a tool call
        Selector->>LLM: Select tool or no tool
        LLM-->>Selector: Structured ToolCall
        Selector-->>Runner: Validated decision

        opt A tool is selected
            Runner->>Tools: Execute registered tool
            Tools-->>Runner: Tool result
            Runner->>Selector: Evaluate next tool decision
        end
    end

    Runner->>LLM: Generate final answer
    LLM-->>Runner: Final response
    Runner-->>Session: ToolAgentResult
    Session->>Session: Store user message and response
    Session-->>CLI: Return result
    CLI-->>User: Display plan and answer
Loading

Design Principles

The language model proposes decisions, but TypeScript controls execution.

  • The model generates plans and proposes tool calls.
  • Zod validates structured outputs.
  • The application validates tool names against the registered catalog.
  • TypeScript executes the actual tool implementations.
  • Tool results are added to the model context.
  • The model generates the final response.

The model does not execute arbitrary code or gain access to system resources simply by requesting a tool.

Project Structure

tslab/
├── src/
│   ├── index.ts          # Interactive CLI
│   ├── agentSession.ts   # Conversation history
│   ├── runToolAgent.ts   # Agent orchestration
│   ├── agent.ts          # Task planning
│   ├── toolAgent.ts      # Tool selection and validation
│   ├── tools.ts          # Tool registry and implementations
│   ├── llm.ts            # Ollama API client
│   └── models.ts         # Zod schemas and TypeScript types
├── tests/
│   ├── tools.test.ts
│   ├── agentSession.unit.test.ts
│   ├── agentSession.test.ts
│   ├── toolAgent.test.ts
│   ├── runToolAgent.test.ts
│   ├── agent.test.ts
│   └── llm.test.ts
├── package.json
├── tsconfig.json
├── vitest.config.ts
├── .gitignore
└── README.md

Technology Stack

Technology Purpose
TypeScript Application logic, types, and tool execution
Node.js Runtime environment
Ollama Local model inference and API
Qwen 3.5 Language model for planning, tool selection, and responses
Zod Runtime validation of structured outputs
Vitest Unit and integration testing
tsx Running TypeScript directly during development
Yarn Dependency management and scripts
Mermaid Architecture and sequence diagrams

Language Model

AgentLab currently uses Qwen 3.5 9B through Ollama.

Property Value
Model identifier qwen3.5:9b
Runtime Ollama
Inference Local
API endpoint http://localhost:11434/api/chat
Output formats Plain text and schema-constrained JSON

Why Qwen 3.5 9B?

A 9-billion-parameter model provides a practical balance between model capability and local resource requirements for experimentation.

Running locally makes it possible to experiment with prompts, structured outputs, and tool-calling workflows without sending ordinary inference requests to a hosted LLM API.

Performance depends on hardware, quantization, context size, and the task being performed. Local execution does not guarantee that model outputs are correct.

Model Responsibilities

The model handles three main tasks:

  1. Planning: Converts a natural-language request into a structured plan.
  2. Tool selection: Decides whether a registered tool is appropriate and explains why.
  3. Response generation: Produces the final answer using the request, conversation history, plan, and available tool results.

How It Works

1. Task Planning

The planner generates an AgentPlan:

type AgentPlan = {
  goal: string;
  steps: string[];
  requires_tools: boolean;
};

The generated plan is parsed and validated against a Zod schema before orchestration continues.

2. Tool Selection

The tool selector generates a ToolCall:

type ToolCall = {
  use_tool: boolean;
  tool: string | null;
  reason: string;
};

A requested tool must exist in the registered tool catalog. Unknown tools and inconsistent decisions are rejected by application validation.

3. Tool Execution

Tools are implemented as ordinary TypeScript functions and registered in tools.ts.

The initial tool is:

Tool Description
get_current_time Returns the current date and time in ISO 8601 format, plus a UTC representation.

The registry makes available capabilities explicit. The model can propose using a tool, but it cannot create new registered capabilities merely by mentioning them in its response.

4. Conversation Memory

AgentSession stores user and assistant messages in memory during the current process.

Previous messages are supplied to the planner, tool selector, and final response generation.

Use reset in the CLI to clear the current conversation history. This memory is in-process only and is not persisted between application restarts.

5. Final Response

After planning and optional tool execution, the orchestrator calls the model to generate the final response.

The result contains the plan, last tool decision, last tool result, and final answer.

Getting Started

Prerequisites

Install the following:

1. Clone the Repository

git clone https://github.com/skantus/agent-lab.git
cd agent-lab

If your local working directory is still named tslab, that is fine. The local folder name does not determine the GitHub repository name.

2. Install Dependencies

yarn install

3. Download the Model

ollama pull qwen3.5:9b

The model download requires several gigabytes of storage.

4. Start Ollama

Ensure the Ollama service is running:

ollama serve

If Ollama is already running as a background service, you do not need to start it again.

5. Verify the Model

ollama list

Confirm that qwen3.5:9b is available.

Running AgentLab

Start the interactive CLI:

yarn dev

Example interaction:

AgentLab ready. Type 'exit' to quit or 'reset' to clear memory.

You: Hi, my name is Alex.

Plan:
Goal: Respond to the user's greeting and acknowledge their name.
1. Understand the user's introduction
2. Respond naturally
Requires tools: false

AgentLab: Nice to meet you, Alex!

You: What is my name?

Plan:
Goal: Retrieve the user's name from conversation history.
1. Review the conversation history
2. Answer using the stored conversation context
Requires tools: false

AgentLab: Your name is Alex.

The exact plan and wording are generated by the model and may differ between runs.

CLI Commands

Command Behavior
reset Clears the conversation history
exit Exits AgentLab

Testing

Unit Tests

yarn test

The unit test suite covers tool execution, tool selection and validation, agent orchestration, and session memory.

Integration Tests

yarn test:integration

Integration tests use the real local Ollama model. They are slower than unit tests and require Ollama and the configured model to be available.

Available Scripts

Command Description
yarn dev Starts the interactive CLI
yarn test Runs the unit test suite
yarn test:integration Runs tests against the local model
yarn test:watch Runs Vitest in watch mode

Current Limitations

AgentLab is an educational implementation, not yet a production-ready autonomous agent.

  • Limited tool catalog: Only the current-time tool is registered.
  • Planner-dependent execution: The planner's requires_tools decision controls whether tool selection runs. An incorrect plan can prevent a needed tool from being considered.
  • Bounded tool loop: Tool selection is limited to three attempts per request.
  • No persistent memory: Conversation history is lost when the process exits.
  • No general-purpose autonomy: The agent does not independently execute every plan step or verify that every goal has been achieved.
  • Model variability: Plans, tool decisions, and responses can vary between runs.
  • Local resource requirements: Model latency and memory usage depend on the machine running Ollama.

These limitations are useful areas for experimentation when learning how agent orchestration works.

Learning Goals

AgentLab explores the fundamentals of AI agent engineering:

  • Prompt engineering and instruction design.
  • Planning and decomposition of natural-language tasks.
  • Structured model outputs and schema validation.
  • Tool calling and capability boundaries.
  • Orchestration of multi-stage LLM workflows.
  • Conversation context and memory.
  • Unit testing versus model integration testing.
  • Local LLM inference and privacy trade-offs.

License

No license has been specified yet. Until a license is added to the repository, reuse and redistribution are not automatically granted.

About

AgentLab is a project built in Typescript focused on understanding how AI agents work internally, exploring task planning, prompt engineering, structured outputs, tool calling, conversation memory, and local language models.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages