During a Sortie session, the agent runs inside a workspace with access to the codebase and the rendered prompt. Sortie also registers tools — structured interfaces that define how agents can query and modify issue tracker data without needing direct API credentials. Sortie scopes all tool operations to the project set in tracker.project.

Info

Currently, tools are prompt-advertised: Sortie appends tool documentation (name, description, input schema, and response format) to the agent's prompt on the first turn. The agent sees the tool contract but cannot invoke it interactively within the session — there is no execution channel (MCP server, HTTP callback, or file-based IPC) wired yet. The tool infrastructure (interface, registry, implementation) is fully built and tested; the missing piece is the runtime bridge between agent and orchestrator. This is coming soon. Once the execution channel is connected, the agent can call tools by name and receive structured responses in turn.


tracker_api

The built-in tool defining read and write access to the configured issue tracker (Jira, GitHub Issues, file-based). The agent does not need its own API key — Sortie uses the tracker credentials from WORKFLOW.md. All operations are scoped to the configured tracker.project; the agent cannot access issues in other projects.

The sections below document the full contract: input schema, operations, response envelope, and error kinds. This is the interface the agent sees advertised in its prompt and the contract that interactive execution will honor once an execution channel is connected.

Input schema

The tool accepts a JSON object with these fields:

Field Type Required Description
operation string Always One of: fetch_issue, fetch_comments, search_issues, transition_issue
issue_id string fetch_issue, fetch_comments, transition_issue The tracker-internal issue ID
target_state string transition_issue The target state name (e.g., "In Review")

No additional fields are accepted. Unknown fields produce an invalid_input error.


Operations

fetch_issue

Retrieve a single issue by its tracker-internal ID. Returns the full issue record.

Request:

{"operation": "fetch_issue", "issue_id": "abc123"}

Response data:

{
  "id": "abc123",
  "identifier": "PROJ-42",
  "title": "Add retry logic to webhook handler",
  "description": "The webhook handler currently fails silently...",
  "state": "In Progress",
  "priority": 2,
  "labels": ["backend", "reliability"],
  "assignee": "alice",
  "issue_type": "Bug",
  "url": "https://mytracker.example.com/browse/PROJ-42",
  "branch_name": "PROJ-42-retry-logic",
  "parent": {"id": "parent-1", "identifier": "PROJ-40"},
  "comments": [
    {"id": "c1", "author": "bob", "body": "Confirmed in prod.", "created_at": "2026-03-25T10:00:00Z"}
  ],
  "blocked_by": [],
  "created_at": "2026-03-20T09:00:00Z",
  "updated_at": "2026-03-25T14:30:00Z"
}

Fields that have no value in the tracker return null (for priority, parent, comments) or "" (for string fields). labels and blocked_by return [] when empty.


fetch_comments

Retrieve comments for a specific issue.

Request:

{"operation": "fetch_comments", "issue_id": "abc123"}

Response data:

[
  {"id": "c1", "author": "alice", "body": "Looks good overall.", "created_at": "2026-03-25T10:00:00Z"},
  {"id": "c2", "author": "bob", "body": "Needs a test for the edge case.", "created_at": "2026-03-25T11:30:00Z"}
]

Each comment contains id, author, body, and created_at (ISO-8601 timestamp).


search_issues

List active-state issues in the configured project. No parameters beyond operation.

Request:

{"operation": "search_issues"}

Response data:

[
  {"id": "abc123", "identifier": "PROJ-42", "title": "Add retry logic", "state": "To Do", "...": "..."},
  {"id": "def456", "identifier": "PROJ-43", "title": "Fix flaky test", "state": "To Do", "...": "..."}
]

Each entry has the same shape as a fetch_issue response. Only issues matching the configured active_states are returned — these are the issues that would be candidates for dispatch, not every issue in the project.


transition_issue

Move an issue to a new state.

Request:

{"operation": "transition_issue", "issue_id": "abc123", "target_state": "In Review"}

Response data:

{"transitioned": true}

The target_state value must match a valid state name in the tracker. If the transition is not allowed by the tracker's workflow rules, the tool returns a tracker_payload_error.


Response envelope

All tracker_api responses use a consistent JSON envelope.

Success:

{
  "success": true,
  "data": { "..." : "..." }
}

The data field contains the operation-specific payload shown in each operation section above.

Failure:

{
  "success": false,
  "error": {
    "kind": "tracker_auth_error",
    "message": "authentication failed: invalid API key"
  }
}

The kind field is a machine-readable category. The message field is a human-readable description.


Error kinds

These error kinds can appear in tracker_api tool responses:

Kind Meaning
invalid_input Malformed request — missing required field, unknown field, or unparseable JSON.
unsupported_operation The operation value is not one of the four recognized operations.
project_scope_violation The requested issue belongs to a different project than the configured tracker.project.
tracker_transport_error Network or connection failure reaching the tracker API. Also returned on request cancellation or deadline exceeded.
tracker_auth_error Authentication failure (HTTP 401/403). The tracker API key is invalid or lacks permissions.
tracker_api_error Tracker API error — rate limiting, 5xx server errors, or other non-200 responses.
tracker_not_found The requested issue does not exist (HTTP 404).
tracker_payload_error Malformed response from the tracker, or an invalid state transition.
internal_error Unexpected internal failure. If you see this, report a bug.

For retry behavior and operator actions for each tracker error kind, see the error reference.


Project scoping

The tool enforces that all operations target issues within tracker.project from WORKFLOW.md. If the agent passes an issue ID that resolves to a different project, the tool returns a project_scope_violation error before performing any mutation.

This is a defense-in-depth measure. The primary access control is the tracker adapter's own API scoping — JQL project filter for Jira, repository scope for GitHub. The tool-level check catches edge cases where the API key happens to have cross-project access.

When tracker.project is empty (e.g., the file-based tracker), project scoping is disabled.


Tool advertising

Sortie advertises tracker_api to the agent automatically. On the first turn of each session, Sortie appends a tool documentation section to the rendered prompt. This section includes the tool name, description, input schema, project scope, and response envelope format. You don't need to describe the tool in your prompt template — the agent already knows it exists.

This is currently prompt-only advertisement — the agent receives the tool contract as text in its prompt context. There is no interactive execution channel yet. The agent cannot call the tool and receive a response within the session. The TrackerAPITool implementation is fully built and tested against mock trackers; what remains is wiring the runtime communication bridge (MCP stdio server or equivalent) so the agent can invoke it.

If the agent calls an unrecognized tool name through a connected execution channel, Sortie returns a failure response and continues the session. It does not stall or crash.


Using tracker_api in prompt templates

Sortie appends the tool description and schema to the prompt automatically — you don't need to reproduce the schema. You can add task-specific guidance about when the agent should use the tool once interactive execution is available:

You have access to the `tracker_api` tool. Use it to:
- Check related issues before starting work: `{"operation": "search_issues"}`
- Read comments for context: `{"operation": "fetch_comments", "issue_id": "..."}`
- Transition the issue when done: `{"operation": "transition_issue", "issue_id": "...", "target_state": "In Review"}`

Today, the agent sees this contract in the prompt but cannot act on it. Including guidance like the above is harmless now and will become functional once the execution channel is connected.