Skip to content
Lenso
English
Esc
navigateopen⌘Jpreview
On this page

Give the Agent a new Tool

Build, install, run, disable, and remove one real Agent Tool Plugin.

In this tutorial you will add an uppercase Tool to the Lenso Agent Host. You will write the behavior once, run it through a real Execution Adapter, package it, install it into an App, ask the Agent to use it, and remove it again.

The current public CLI scaffolds Plugins; it does not scaffold a generic product Host. This tutorial therefore uses the maintained Lenso Agent as the concrete Host.

Complete Run your first Agent Turn first. This tutorial starts from an installed, authenticated Host and its visible Plugin Root:

lenso-agent-cli doctor --json
mkdir -p "$HOME/.lenso/agent/plugins"
lenso plugins list --root "$HOME/.lenso/agent"

What you will build

company.uppercase Plugin
  provides lenso.agent.tool-provider@2
  packages Wasm + trusted Process implementations
  installs into ~/.lenso/agent/plugins/
  becomes the uppercase Tool in the Agent App

1. Install the authoring tools

You need Rust 1.94 or newer, the Wasm target, Git, and either distribution of the Lenso CLI:

rustup target add wasm32-unknown-unknown
npm install -g @lenso/cli
# or: cargo install lenso-cli

Confirm the workflow exposed by your installed version:

lenso --version
lenso plugin new --help

2. Create the Plugin

Run this in an empty tutorial directory:

lenso plugin new company.uppercase
cd company.uppercase

The default Rust project has one editable src/lib.rs. It produces a portable Wasm implementation and a trusted native Process implementation of the same Plugin Contract.

Replace the generated execute body with uppercase behavior:

fn execute(arguments: Arguments) -> Result<ExecuteResponse, ExecuteError> {
    if arguments.text.is_empty() {
        return Err(ExecuteError::InvalidArguments);
    }

    Ok(ExecuteResponse {
        content: arguments.text.to_uppercase(),
        content_type: ContentType::Text,
        metadata_json: r#"{"operation":"uppercase"}"#
            .try_into()
            .expect("static metadata is valid JSON"),
    })
}

Keep the generated #[lenso::plugin], #[tool_provider], and #[tool] annotations. They own the Plugin descriptor and Agent Tool projection.

3. Run it before packaging

lenso plugin check
lenso plugin dev \
  --implementation auto \
  --operation execute \
  --request-json '{"name":"company.uppercase","arguments_json":"{\"text\":\"hello lenso\"}"}'

The result contains HELLO LENSO. For a multi-output Rust project, auto uses the fastest declared local implementation. Run --implementation wasm and --implementation process when you need implementation-specific evidence.

During editing, rerun automatically with the same request:

lenso plugin dev --watch \
  --operation execute \
  --request-json '{"name":"company.uppercase","arguments_json":"{\"text\":\"hello lenso\"}"}'

4. Package one Release

lenso plugin pack

The command creates and reopens dist/company.uppercase-0.1.0.lenso-plugin. That archive contains both implementations and one shared Contract.

Keep the absolute bundle path before leaving the Plugin directory:

PLUGIN_BUNDLE="$PWD/dist/company.uppercase-0.1.0.lenso-plugin"

5. Load the installed Host Catalog

lenso-agent-cli contexts --profile code

The contexts command boots the Host without starting a model Turn and publishes the matching Host Catalog. The App owner changes only the visible Plugin Root under ~/.lenso/agent/plugins/.

6. Add the Plugin to the App

lenso plugins add "$PLUGIN_BUNDLE" --root "$HOME/.lenso/agent"
lenso plugins list --root "$HOME/.lenso/agent"
lenso app check --root "$HOME/.lenso/agent"

plugins add validates the received Bundle, derives a candidate App from the Host Catalog and Plugin Root, and commits the files only when the candidate is valid.

7. Use the new behavior

From any Workspace where you want the Agent to work:

lenso-agent-cli --profile code \
  "Use company.uppercase to convert 'hello lenso' to uppercase."

The observable result is an Agent Turn that calls company.uppercase and returns HELLO LENSO. The Plugin is now application behavior, not only a locally callable package.

8. Disable, enable, and remove it

lenso plugins disable company.uppercase default --root "$HOME/.lenso/agent"
lenso plugins enable company.uppercase default --root "$HOME/.lenso/agent"
lenso plugins remove company.uppercase --root "$HOME/.lenso/agent"
lenso app check --root "$HOME/.lenso/agent"

Disable keeps the package and configuration available. Omitting the Instance key from remove deletes the whole Plugin directory and moves it into the App’s recoverable .lenso/trash/. In both cases the Host resolves a new immutable App Generation; existing work keeps the Generation on which it started.

You have now completed the full author workflow. Continue with Choose a Plugin path when the next behavior is not an Agent Tool, or Add Plugins to an App for configuration, resources, and Catalog operations.

Clone the Agent repository only when you need to change the Host’s Rust implementation. The source-development path is documented in the Agent README.

Last updated on September 6, 2026

Was this page helpful?