> ## Documentation Index
> Fetch the complete documentation index at: https://cadenya.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Wrap an HTTP API

> Define a typed HTTP tool in the dashboard, then call it from an agent objective.

Use the HTTP adapter when an API has no OpenAPI specification, or when you want to expose only a few hand-designed operations. The tool set stores a shared base URL and headers. Each tool defines its method, path, arguments, and optional request body.

This guide wraps JSONPlaceholder's public todo endpoint as a read-only `GetTodo` tool. You configure it in the dashboard, then verify the live request from code.

## What you need

* A Cadenya workspace.
* A published agent, or permission to create one with [Create and publish an agent](/docs/guides/configure-a-simple-agent).
* `CADENYA_API_KEY` and `CADENYA_WORKSPACE_ID` for the code examples.

## Create the HTTP tool set

<Steps>
  <Step title="Set the shared connection">
    Select **Tool Sets**, click **Create Tool Set**, and select **HTTP**. Enter this **Base URL**:

    ```text theme={null}
    https://jsonplaceholder.typicode.com
    ```

    <Frame caption="A shared base URL for every tool in the set">
      <img src="https://mintcdn.com/cadenya/H-RL7Q6kGrFhr6Gf/images/docs/tool-sets/http-connection.webp?fit=max&auto=format&n=H-RL7Q6kGrFhr6Gf&q=85&s=a4a00767b547f708e9b3b4803aba61e8" alt="HTTP connection step with JSONPlaceholder entered as the base URL" width="3016" height="778" data-path="images/docs/tool-sets/http-connection.webp" />
    </Frame>

    Use **Add header** when every endpoint needs the same value. Store credentials as [secrets](/docs/guides/store-and-use-secrets) and reference them as `${SECRET_NAME}`:

    ```text theme={null}
    Authorization: Bearer ${TODO_API_TOKEN}
    ```

    Tool-level headers can add or override values for one endpoint.
  </Step>

  <Step title="Name and create the set">
    Click **Continue** and enter:

    | Field       | Value                                            |
    | :---------- | :----------------------------------------------- |
    | Name        | `Public Todos`                                   |
    | Description | `Read public todo records from JSONPlaceholder.` |
    | External ID | `public-todos`                                   |

    Review the configuration, then click **Create Tool Set**.

    The new **Tools** tab is empty. HTTP tool sets do not discover operations. You define each tool explicitly.
  </Step>
</Steps>

## Add the read-only tool

On the **Tools** tab, click **Add Tool**.

### Describe the model-facing call

Enter:

| Field             | Value                                         |
| :---------------- | :-------------------------------------------- |
| Name              | `get_todo`                                    |
| Description       | `Get a public todo record by its numeric ID.` |
| Requires Approval | **Not required**                              |

Under **Parameters**, click **Convert a JSON payload to a schema** and paste:

```json theme={null}
{
  "todoId": 1
}
```

Click **Convert**, inspect the inferred schema, then click **Accept**. The resulting JSON Schema requires one integer named `todoId`.

The metadata **Name** identifies the Cadenya resource. **Tool Name** is the function name sent to the model. Keeping those names separate lets you use a conventional resource name while giving the model a concise operation name.

### Configure the request

Under **HTTP configuration**, enter:

| Field          | Value                           |
| :------------- | :------------------------------ |
| Request Method | **GET**                         |
| Path           | `/todos/{{ arguments.todoId }}` |
| Query          | Leave empty                     |
| Tool Name      | `GetTodo`                       |

<Frame caption="A GET path rendered from the model's validated argument">
  <img src="https://mintcdn.com/cadenya/H-RL7Q6kGrFhr6Gf/images/docs/tool-sets/http-tool-form.webp?fit=max&auto=format&n=H-RL7Q6kGrFhr6Gf&q=85&s=38518376c3350c78b52ca599622c8038" alt="HTTP tool configuration with GET, a Liquid path using arguments.todoId, and GetTodo as the tool name" width="1910" height="1080" data-path="images/docs/tool-sets/http-tool-form.webp" />
</Frame>

The parameter schema controls what the model may send. Liquid renders those validated values into the request:

```text theme={null}
Base URL: https://jsonplaceholder.typicode.com
Path:     /todos/{{ arguments.todoId }}
Argument: { "todoId": 7 }
Request:  GET https://jsonplaceholder.typicode.com/todos/7
```

<Warning>
  Keep the `arguments.` prefix. `{{ arguments.todoId }}` reads the tool argument; `{{ todoId }}` does not.
</Warning>

Click **Create tool**.

## Verify the saved tool

The **Tools** tab now reports one available tool. Select `get_todo` and confirm:

* The LLM tool name is `GetTodo`.
* The adapter badge is **HTTP**.
* The parameter schema requires integer `todoId`.
* Approval is not required.

<Frame caption="The available GetTodo tool and its parameter schema">
  <img src="https://mintcdn.com/cadenya/H-RL7Q6kGrFhr6Gf/images/docs/tool-sets/http-tool-details.webp?fit=max&auto=format&n=H-RL7Q6kGrFhr6Gf&q=85&s=3b5f3d673bd9c27bc6f99aa890bf83c0" alt="Public Todos tool set showing get_todo as an available HTTP tool with GetTodo as its LLM name" width="2664" height="2456" data-path="images/docs/tool-sets/http-tool-details.webp" />
</Frame>

HTTP tools do not have sync events because their definitions live in Cadenya. Edit the tool whenever its request or model-facing schema changes.

## Assign the tool set to an agent

Open an agent variation, add `Public Todos` under **Assignments**, and use a system prompt such as:

```text theme={null}
Use GetTodo with the numeric ID from the user.
Return a compact JSON object containing id, title, and completed from the result.
```

Publish the agent after saving the assignment.

## Dispatch a todo lookup

Set `CADENYA_AGENT_ID` to the published agent's ID, then choose an example:

<CodeGroup>
  ```typescript TypeScript theme={null}
  import Cadenya from '@cadenya/cadenya';

  const client = new Cadenya({ apiKey: process.env['CADENYA_API_KEY'] });
  const workspaceId = process.env['CADENYA_WORKSPACE_ID']!;
  const agentId = process.env['CADENYA_AGENT_ID']!;

  const objective = await client.objectives.create({
    workspaceId,
    agentId,
    systemPromptData: {},
    firstUserMessage: 'Get todo 7.',
  });

  console.log(objective.metadata.id);
  ```

  ```bash cURL theme={null}
  curl "https://api.cadenya.com/v1/workspaces/${CADENYA_WORKSPACE_ID}/objectives" \
    -H "Authorization: Bearer ${CADENYA_API_KEY}" \
    -H "Content-Type: application/json" \
    -d "{
          \"agentId\": \"${CADENYA_AGENT_ID}\",
          \"systemPromptData\": {},
          \"firstUserMessage\": \"Get todo 7.\"
        }"
  ```
</CodeGroup>

The vetted run produced:

```text theme={null}
userMessage → assistantMessage → toolCalled → toolResult → assistantMessage
```

The tool call contained `{ "todoId": 7 }`. JSONPlaceholder returned todo 7, and the agent replied:

```json theme={null}
{
  "id": 7,
  "title": "illo expedita consequatur quia in",
  "completed": false
}
```

## Create the same resources from the SDK

Provisioning code creates the empty HTTP tool set and then adds each operation:

```typescript theme={null}
const toolSet = await client.toolSets.create({
  workspaceId,
  metadata: { name: 'Public Todos', externalId: 'public-todos' },
  spec: {
    description: 'Read public todo records from JSONPlaceholder.',
    adapter: {
      type: 'http',
      http: { baseUrl: 'https://jsonplaceholder.typicode.com' },
    },
  },
});

const tool = await client.toolSets.tools.create(toolSet.metadata.id, {
  workspaceId,
  metadata: { name: 'get_todo', externalId: 'get-todo' },
  spec: {
    description: 'Get a public todo record by its numeric ID.',
    requiresApproval: false,
    parameters: {
      type: 'object',
      properties: {
        todoId: { type: 'integer' },
      },
      required: ['todoId'],
    },
    llmToolName: 'GetTodo',
    config: {
      type: 'http',
      http: {
        requestMethod: 'GET',
        path: '/todos/{{ arguments.todoId }}',
      },
    },
  },
});
```

## Configure other request shapes

Every templated field reads from the same `arguments` object.

### Query parameters

Keep the path stable and render the query separately:

```text theme={null}
Path:  /search
Query: q={{ arguments.query }}&limit={{ arguments.limit }}
```

Include both `query` and `limit` in the tool's parameter schema.

### JSON request bodies

For `POST`, `PUT`, or `PATCH`, set **Request Body Content Type** and **Request Body Template**:

```text theme={null}
Request Body Content Type: application/json
Request Body Template:
{ "todoId": {{ arguments.todoId }}, "completed": {{ arguments.completed }} }
```

The path, query, headers, and body all support Liquid. Make the parameter schema match the values the template renders.

### Approval for writes

Select **Required** for tools that change data, send messages, move money, or trigger another sensitive action. The objective pauses before Cadenya sends the request. Your application can then [approve or deny the tool call](/docs/guides/callbacks/approving-a-tool).

## Trace requests

Cadenya adds correlation headers to every HTTP call:

| Header                         | Identifies             |
| :----------------------------- | :--------------------- |
| `x-cadenya-tool-call-id`       | The tool call          |
| `x-cadenya-objective-id`       | The objective          |
| `x-cadenya-agent-id`           | The agent              |
| `x-cadenya-agent-variation-id` | The selected variation |

Log these values on the receiving service to connect its request record to the Cadenya timeline.

<Check>
  You now have a hand-defined HTTP tool whose UI schema, Liquid path, live GET request, tool result, and agent response have all been verified.
</Check>

## Next steps

<CardGroup cols={2}>
  <Card title="Require approval" icon="user-check" href="/docs/guides/callbacks/approving-a-tool">
    Pause sensitive HTTP writes before Cadenya sends them.
  </Card>

  <Card title="Store credentials" icon="key" href="/docs/guides/store-and-use-secrets">
    Put provider tokens behind secret references.
  </Card>

  <Card title="Run tools in your code" icon="code" href="/docs/guides/tool-sets/bare">
    Keep execution inside a private worker instead of exposing an endpoint.
  </Card>

  <Card title="Tool sets from the SDK" icon="brackets-curly" href="/docs/guides/sdk/tool-sets">
    Manage tools, assignments, updates, and archival from code.
  </Card>
</CardGroup>
