# Tools

Manage organization-scoped, versioned capabilities ("tools"). This page documents the core API endpoints and expected request/response shapes.

{% hint style="info" %}
**API Terminology** In the API, these are called "Tools." In our conceptual documentation, we refer to them as "Actions" - the execution layer that transforms agent reasoning into real-world outcomes. See [Conceptual Docs: Actions](https://docs.amigo.ai/agent/actions) for the architectural perspective. Tools are organization-scoped and versioned; use the OpenAPI embeds below for exact request/response shapes and parameters.
{% endhint %}

{% hint style="info" %}
**Platform API uses Skills instead** - Classic API Tools are versioned code packages from Git. The Platform API uses [Skills](https://docs.amigo.ai/developer-guide/platform-api/platform-api/skills) - LLM-backed declarative micro-agents. Choose Tools for custom code execution, Skills for LLM-native reasoning.
{% endhint %}

## Scope & Behavior

* All operations are organization‑scoped.
* Related operations are serialized per tool; concurrent publish/deprecate on the same tool returns HTTP 409.
* Tool output visibility is controlled by the `result_persistence` property configured in Context Graph tool call specifications (see [Tool Result Persistence](#tool-result-persistence)).

## How Tools Work (Actions)

Tools run as versioned actions. At a high level:

* Versioned builds: When you publish, the platform builds your tool from your team branch, pins the source commit, and creates a new immutable version (semantic versioning).
* Org‑scoped execution: Each organization's tools and versions are isolated and only callable within that org.
* Managed runtime per execution: Runs execute in a managed environment with the variables you configured for the tool; tool state is versioned and not persisted between runs.
* Typed contracts: Your tool project defines inputs/outputs and checks; publishing runs validations and fails if required pieces are missing.
* Configuration first: Environment variables (regular and secret) must exist on the tool before publishing versions that require them; in‑use variables cannot be deleted.
* Rollout control: Publish adds a new version alongside older ones; you choose when to deprecate specific versions or the entire tool. Deprecation removes those versions from new runs.
* Observability & traceability: Each version records who published it and the pinned source details. Use your org's monitoring to track latency, errors, and usage by version.

### Execution Modes

Tools have two execution modes, defined by the `invocation_mode` parameter when invoking a tool:

* **`regular`**: Used for production conversations with real users. Tools should perform actual operations (API calls, database updates, external integrations, etc.) in this mode.
* **`conversation-simulation`**: Used for testing and simulation scenarios. Tools may need to mock external calls, use test data, or adjust behavior to avoid side effects during automated testing.

When implementing a tool, handle both modes appropriately in your code. The `invocation_mode` is passed as part of each input in the invocation request and can be accessed within your tool's execution logic to determine the appropriate behavior.

### Tool Entry Point Signature

Your tool's `run_tool()` function must accept the following six parameters:

```python
from amigo_tool_scaffold.user_variables import UserVariables

async def run_tool(tool_input, metadata, config, conversation, send_status_event, user_variables: UserVariables):
    ...
```

| Parameter           | Description                                                                                                 |
| ------------------- | ----------------------------------------------------------------------------------------------------------- |
| `tool_input`        | The input parameters passed to the tool                                                                     |
| `metadata`          | Execution metadata (invocation mode, tool version, etc.)                                                    |
| `config`            | Tool environment variables and configuration                                                                |
| `conversation`      | Conversation context                                                                                        |
| `send_status_event` | Callback for sending status events during execution                                                         |
| `user_variables`    | Key-value pairs configured on the user's profile, useful for external system IDs and tool-specific settings |

{% hint style="warning" %}
**Signature Change (v0.3.24)** The `user_variables` parameter was added in Agent Forge v0.3.24. Tools with the old 5-parameter signature will fail CI checks. Update your tool's entry point to include the new parameter.
{% endhint %}

#### Typical lifecycle

1. Create the tool (name, description, tags).
2. Add required environment variables for the tool.
3. Test the tool from a branch before publishing.
4. Publish a version from your team branch (choose major/minor/patch).
5. Invoke directly or call from your application/SDK.
6. Query invocation history for debugging and audit.
7. Iterate by publishing new versions; deprecate older ones when ready.

### Workflow (diagram)

{% @mermaid/diagram content="%%{init: {"flowchart": {"useMaxWidth": true, "nodeSpacing": 20, "rankSpacing": 30}, "theme": "base", "themeVariables": {"primaryColor": "#D4E2E7", "primaryTextColor": "#100F0F", "primaryBorderColor": "#083241", "lineColor": "#575452", "textColor": "#100F0F", "clusterBkg": "#F1EAE7", "clusterBorder": "#D7D2D0"}}}%%
flowchart TB
A\[Create Tool]
B\[Configure Env Vars]
C\[Test on Branch]
D\[Publish Version]
E\[Version Pinned]
F\[Use from App/SDK]
G\[Direct Invoke]
H\[Tool Executes]
I\[Invocation Recorded]
J\[Query/Search History]
K\[Deprecate Versions]

A --> B --> C
C -.iterate.-> B
C --> D --> E
E --> F & G
F & G --> H --> I --> J
E -.-> K
K -.-> E

style C fill:#DDE3DB,stroke:#2c3827,color:#100F0F
style G fill:#DDE3DB,stroke:#2c3827,color:#100F0F
style J fill:#DDE3DB,stroke:#2c3827,color:#100F0F" %}

## Tool Availability by State

The agent only sees tools listed in the current state's tool call specifications. There is no global tool pool - when the agent transitions between states, its available tools change to match the new state's configuration.

Tool execution is validated against a snapshot of the tools presented to the LLM at the start of each turn, rather than re-querying the current state. This prevents time-of-check/time-of-use inconsistencies if a state transition occurs during tool execution.

{% hint style="info" %}
System tools (e.g., `forward_call`, `get_tool_call_status`) are handled separately by the platform and do not need to be listed in state tool call specs.
{% endhint %}

## Tool Result Persistence

When tools are configured in Context Graphs (API: `service_hierarchical_state_machine`), each tool call specification includes a `result_persistence` property that controls how tool outputs are stored and made available to the agent across interactions.

<details>

<summary>Persistence modes reference table</summary>

#### Persistence Modes

The `result_persistence` property can take three values:

| Value                   | Behavior                                                                                                                                                                                                | Use Case                                                                                                                                                    |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `"ephemeral"`           | Tool result is visible only during the current LLM interaction (e.g., parameter generation, action selection) and is **not** persisted in the conversation log for future interactions.                 | Large outputs only needed for immediate decision-making; temporary processing results; intermediate computation steps that don't require long-term context. |
| `"persisted-preferred"` | Tool result is persisted in all future interaction logs **if** output is less than 5k characters. Outputs exceeding 5k characters are automatically treated as ephemeral and excluded from future logs. | Most general-purpose tools where results should be available to the agent when possible, with graceful handling of unexpectedly large outputs.              |
| `"persisted"`           | Tool result is persisted in all future interaction logs **if** output is less than 5k characters. Outputs exceeding 5k characters cause the tool invocation to **throw an error**.                      | Critical tools whose outputs must always be available to the agent; tools designed never to produce large outputs (e.g., status lookups, account queries).  |

</details>

{% hint style="warning" %}
**Important Limits**

* Individual tool outputs have a 20k character limit (enforced during tool execution)
* Persistence thresholds are 5k characters (for `"persisted"` and `"persisted-preferred"` modes)
  {% endhint %}

<details>

<summary>Configuration by Context Graph state type</summary>

#### Configuration

The `result_persistence` property is configured within tool call specifications in your Context Graph state definitions (API: `service_hierarchical_state_machine`). Different state types support tool call specs in different contexts:

| State Type          | Field                                                 | Description                                              |
| ------------------- | ----------------------------------------------------- | -------------------------------------------------------- |
| **ActionState**     | `action_tool_call_specs[].result_persistence`         | Tools used during action execution                       |
| **ActionState**     | `exit_condition_tool_call_specs[].result_persistence` | Tools used when evaluating exit conditions               |
| **DecisionState**   | `tool_call_specs[].result_persistence`                | Helper tools during decision-making                      |
| **ReflectionState** | `tool_call_specs[].result_persistence`                | Helper tools during reflection generation                |
| **ToolCallState**   | `tool_call_specs[].result_persistence`                | Helper tools during designated tool parameter generation |

</details>

#### Example Configuration

```json
{
  "type": "action",
  "name": "customer_support",
  "action_tool_call_specs": [
    {
      "tool_id": "670a1234567890abcdef1234",
      "version_constraint": ">=1.0.0",
      "additional_instruction": "Search the knowledge base for relevant articles",
      "audio_fillers": ["Let me search for that..."],
      "audio_filler_triggered_after": 2.0,
      "result_persistence": "persisted-preferred"
    }
  ]
}
```

### Best Practices

1. **Prefer `"persisted-preferred"` for most tools**: Provides the best balance between context availability and graceful handling of large outputs.
2. **Use `"ephemeral"` for large or transient data**: Tools returning large datasets, file contents, or verbose debugging information should use `"ephemeral"` to prevent context bloat and maintain efficient agent performance.
3. **Use `"persisted"` for critical context**: Tools whose outputs are essential for conversation continuity (user account lookups, order status, entity resolution) should use `"persisted"` to guarantee agent access to results.
4. **Design concise tool outputs**: Structure outputs to stay under 5k characters when possible by returning summaries, structured data, or references rather than full raw content.

## Create a Tool

Create a new tool with metadata (name, description, tags).

{% openapi src="<https://api.amigo.ai/v1/openapi.json>" path="/v1/{organization}/tool/" method="post" %}
<https://api.amigo.ai/v1/openapi.json>
{% endopenapi %}

## List Tools

Common filters:

* `id=<id>` (repeatable), `deprecated=true|false`
* `tag=key:value` (repeatable; `value` may be `*` or empty for null)
* `sort_by=+name|-name|+deprecated|-deprecated` (repeatable)
* `limit` (1-20, default 10), `continuation_token` (int, default 0)

{% openapi src="<https://api.amigo.ai/v1/openapi.json>" path="/v1/{organization}/tool/" method="get" %}
<https://api.amigo.ai/v1/openapi.json>
{% endopenapi %}

## Update a Tool

Update tool metadata (name, description, tags).

{% openapi src="<https://api.amigo.ai/v1/openapi.json>" path="/v1/{organization}/tool/{tool\_id}" method="post" %}
<https://api.amigo.ai/v1/openapi.json>
{% endopenapi %}

## Manage Tool Environment Variables

Notes:

* Names must match `[A-Z_]+`.
* Variables required by any non‑deprecated version cannot be deleted.

{% openapi src="<https://api.amigo.ai/v1/openapi.json>" path="/v1/{organization}/tool/{tool\_id}/envvar" method="post" %}
<https://api.amigo.ai/v1/openapi.json>
{% endopenapi %}

## Test a Tool

Test a tool from a specific repository branch without publishing. Runs CI checks and executes the tool with supplied inputs.

{% hint style="info" %}
Test inputs must include both `input_parameters` and `invocation_mode` (typically `"regular"` for testing production behavior or `"conversation-simulation"` for testing simulation behavior).
{% endhint %}

{% openapi src="<https://api.amigo.ai/v1/openapi.json>" path="/v1/{organization}/tool/test" method="post" %}
<https://api.amigo.ai/v1/openapi.json>
{% endopenapi %}

## Publish a Tool Version

Behavior:

* Computes next semantic version (or `1.0.0` if none), validates, builds, and publishes.
* Long-running (1-5 minutes). Serialized per tool. Returns 409 if a related operation is in progress.

Repo guidance:

* `repo: "team"` publishes from your team's branch (for example, `releases/<TEAM>`). Use this for all organization-specific tools.
* `repo: "main"` is reserved for the scaffold and canonical, shared tools; do not use it for organization-specific publishing.

{% hint style="warning" %}
Publishing is a long‑running operation (typically 1-5 minutes). Adjust client timeouts accordingly.
{% endhint %}

{% openapi src="<https://api.amigo.ai/v1/openapi.json>" path="/v1/{organization}/tool/{tool\_id}/version" method="post" %}
<https://api.amigo.ai/v1/openapi.json>
{% endopenapi %}

## List Tool Versions

Common filters:

* `deprecated=true|false`
* `version_constraint=<pep440 constraint>` (e.g., ">=1.2,<2")
* `creator=<org_id,user_id>` (repeatable)
* `sort_by=+created_at|-created_at|+version.major|...|+deprecated|-deprecated` (repeatable)
* `limit` (0-50, default 50), `continuation_token` (int)

{% openapi src="<https://api.amigo.ai/v1/openapi.json>" path="/v1/{organization}/tool/{tool\_id}/version" method="get" %}
<https://api.amigo.ai/v1/openapi.json>
{% endopenapi %}

## Invoke a Tool Version

Execute a tool version with up to 10 inputs in parallel. Each invocation returns the output and execution duration, or an error if the invocation fails.

{% hint style="info" %}
Each input must include:

* `input_parameters`: An object containing the parameters expected by your tool
* `invocation_mode`: Either `"regular"` (for production use) or `"conversation-simulation"` (for testing)

See [Execution Modes](#execution-modes) for details on how to implement mode-specific behavior.
{% endhint %}

{% openapi src="<https://api.amigo.ai/v1/openapi.json>" path="/v1/{organization}/tool/{tool\_id}/version/{version}/invoke" method="post" %}
<https://api.amigo.ai/v1/openapi.json>
{% endopenapi %}

## Get Tool Invocations

Retrieve historical tool invocations across conversations and simulations. All invocations are recorded regardless of success or rollback status.

{% hint style="info" %}
When interactions are rolled back, the associated tool invocations remain in history but `conversation_id`, `interaction_id`, and `simulation_run_id` fields are nullified.
{% endhint %}

Common filters:

* `tool_id=<tool_id>`
* `version=<pep440 constraint>` (e.g., ">=1.2,<2")
* `invocation_source_type=conversation|simulation`
* `conversation_id=<id>`
* `succeeded=true|false`

{% openapi src="<https://api.amigo.ai/v1/openapi.json>" path="/v1/{organization}/tool/invocation" method="get" %}
<https://api.amigo.ai/v1/openapi.json>
{% endopenapi %}

## Search Tool Invocations

Search tool invocations by text query across outputs, error messages, and stack traces.

{% openapi src="<https://api.amigo.ai/v1/openapi.json>" path="/v1/{organization}/tool/invocation/search" method="get" %}
<https://api.amigo.ai/v1/openapi.json>
{% endopenapi %}

## Deprecate Tool Versions

Remove specific tool versions from production use.

Notes:

* `versions` is a semantic version constraint (PEP 440 style), e.g., `>=1.0,<2`.
* Response: 204 No Content

{% hint style="info" %}
Cost note\
Deprecate versions that are no longer referenced in your applications to control storage‑related costs.
{% endhint %}

{% openapi src="<https://api.amigo.ai/v1/openapi.json>" path="/v1/{organization}/tool/{tool\_id}/version/{versions}" method="delete" %}
<https://api.amigo.ai/v1/openapi.json>
{% endopenapi %}

## Deprecate a Tool

Behavior:

* Marks the tool and all its versions as deprecated and removes runtime versions.
* Propagation across the system can take \~1 minute.

{% openapi src="<https://api.amigo.ai/v1/openapi.json>" path="/v1/{organization}/tool/{tool\_id}" method="delete" %}
<https://api.amigo.ai/v1/openapi.json>
{% endopenapi %}

## Tool Scaffold Setup (CLI)

The `forge tool-scaffold install` command automates installation of the `amigo_tool_scaffold` package into your tool directories, handling authentication and package manager configuration in a single step.

```bash
# Interactive tool selection
forge tool-scaffold install -e myorg

# Install in a specific tool
forge tool-scaffold install -e myorg --tool my_tool

# Install in all tools
forge tool-scaffold install -e myorg --all

# Verbose output for debugging
forge tool-scaffold install -e myorg --all --verbose
```

| Option             | Required | Description                          |
| ------------------ | -------- | ------------------------------------ |
| `--env` / `-e`     | Yes      | Environment name                     |
| `--tool` / `-t`    | No       | Install in a specific tool directory |
| `--all`            | No       | Install in all tool directories      |
| `--verbose` / `-v` | No       | Enable verbose output                |

{% hint style="info" %}
**Prerequisite**: Requires `uv >= 0.10.2`. The command validates the `uv` version at startup and provides a clear error if it is missing or outdated.
{% endhint %}

## Download Tool Scaffold

Download the latest tool scaffold release as a `.tar.gz` archive. The scaffold provides the base project structure for building new tools.

{% hint style="info" %}
**CLI Alternative** For most workflows, use the `forge tool-scaffold install` command instead of this endpoint directly. See [Tool Scaffold Setup (CLI)](#tool-scaffold-setup-cli) above.
{% endhint %}

{% openapi src="<https://api.amigo.ai/v1/openapi.json>" path="/v1/{organization}/tool/amigo\_tool\_scaffold.tar.gz" method="get" %}
<https://api.amigo.ai/v1/openapi.json>
{% endopenapi %}

## Tool Git Interface

Access the underlying tool repository for the organization through the standard Git interface. These endpoints serve as the Git URL for the tool repo and support all standard Git operations through [Git protocol version 2](https://git-scm.com/docs/http-protocol#_smart_clients) over HTTPS.

**Permission required:** `Tool:AccessRepo`

{% hint style="info" %}
**Git Client Configuration** Configure your Git client to use these endpoints as the remote URL. Most Git clients default to protocol version 2, which is required.

```bash
git clone https://api.amigo.ai/v1/<YOUR-ORG-ID>/tool/git/<path>
```

{% endhint %}

{% openapi src="<https://api.amigo.ai/v1/openapi.json>" path="/v1/{organization}/tool/git/{git\_path}" method="get" %}
<https://api.amigo.ai/v1/openapi.json>
{% endopenapi %}

{% openapi src="<https://api.amigo.ai/v1/openapi.json>" path="/v1/{organization}/tool/git/{git\_path}" method="post" %}
<https://api.amigo.ai/v1/openapi.json>
{% endopenapi %}

## Related

* Classic API → [Tool Repository](https://docs.amigo.ai/developer-guide/classic-api/core-api/tool-repository) - Browse tool source code, branches, commits, and diffs
* Getting Started → [Authentication](https://docs.amigo.ai/developer-guide/getting-started/authentication)
* Getting Started → [Regions & Endpoints](https://docs.amigo.ai/developer-guide/getting-started/regions-and-endpoints)
* Core API → [Services](https://docs.amigo.ai/developer-guide/classic-api/core-api/services)
* Best Practices → [Version Sets & Promotion](https://docs.amigo.ai/developer-guide/operations/devops/version-sets-best-practices)
