---
title: "What happened in the task, and who did it [read]"
method: GET
path: "/tasks/{id}/story"
tags: ["tasks"]
---

# What happened in the task, and who did it \[read\]

`GET /tasks/{id}/story`

## Request

- Base URL: `https://api.agentsky.dev/v1`
- URL: `https://api.agentsky.dev/v1/tasks/{id}/story`
- Auth: HTTP bearer

One time-ordered list assembled from what the task's sessions, files, artifacts and connector calls already recorded and from the task's work graph events: each message with who sent it (a person, an agent, a workspace key or a share-link guest), each tool call an agent's message carries (tool, a short summary of its arguments, ok or error), the sessions it started, requests and their answers, decisions and outcomes, mentions and assignments, task file versions, artifact publications and comments, connector calls (app, method, host, status, and the person whose turn made the call), recorded meetings, every other event of the task by its own kind (connector and context results with links to their stored bodies, stored files, handoffs, GitHub pull requests and checks linked to a session), and each session's cost. An event that describes a row already listed appears once. Nothing is stored. Each part follows its own read rule: a session the caller may only view contributes its messages' text and nothing else; an artifact appears only when the caller may open it; events come from the task's workspace log and the caller's own private log only, so a teammate's connector replies are never shown. The story has no size limit: page through it with `cursor`. With by=session, a helper or handoff session's id names its task. 400 `invalid_request` for a cursor this route did not return or an `order` that differs from the cursor's.

## Path parameters

- `id` string, required

## Query parameters

- `limit` integer
- `order` 'asc' | 'desc'
- `cursor` string
- `by` 'session'

## Response `200`

OK

- object
  - `story` TaskStory, required
    - `task_id` string, required
    - `title` string, nullable, required
    - `sessions` object[], required
      - `id` string, required
      - `role` 'primary' | 'helper' | 'handoff', required
      - `title` string, nullable, required
      - `agent_type` string, required
      - `llm` string, required
      - `started_by` StoryActor, required: Who did it. `person` is named as the workspace knows them (a null user_id is someone the record does not name, such as a file written through the API); `agent` names the session it ran in; `key` is a workspace key; `guest` wrote through a share link; `platform` raised it itself.
        - `kind` 'person' | 'agent' | 'key' | 'guest' | 'platform', required
        - `user_id` string, nullable
        - `name` string, nullable
        - `session_id` string
        - `agent_type` string
        - `key_id` string
      - `created_at` string, date-time, required
      - `consumed_cost` MonetaryAmount, required: A US-dollar amount. `amount` is whole US cents as an integer decimal string — "125" is $1.25 — rounded half-up to the cent.
        - `amount` string, required: Whole US cents
        - `currency` 'USD', required
        - `unit` 'cents': The unit of `amount`; present on every amount the API returns
        - `amount_usd` string: The exact amount in US dollars, up to six decimals — "0.0038" for spend that rounds to 0 cents. Returned, never accepted.
      - `visibility` 'full' | 'messages', required: `messages`: the caller may only view this session, so only its messages' text is in the story
    - `people` object[], required: Everyone this page names, and every session's owner
      - `user_id` string, required
      - `name` string, required
    - `entries` StoryEntry[], required: In the page's `order`; without `order` or `cursor`, the newest `limit` entries oldest first
      - `id` string, required: Stable for the row it was read from
      - `at` string, date-time, required
      - `kind` string, required: One of `session.started`, `message`, `tool.call`, `request.asked`, `request.answered`, `decision`, `outcome`, `mention`, `assignment`, `file.changed`, `artifact.published`, `artifact.comment`, `connector.call`, `meeting.recorded`; any other value is a work graph event's own kind (`result.obtained`, `file.stored`, `handoff.requested`, `github.pr_opened`, …), and new kinds appear without notice
      - `session_id` string, nullable, required: The task session it happened in; null for task files and artifact comments not tied to one
      - `actor` StoryActor, required: Who did it. `person` is named as the workspace knows them (a null user_id is someone the record does not name, such as a file written through the API); `agent` names the session it ran in; `key` is a workspace key; `guest` wrote through a share link; `platform` raised it itself.
        - `kind` 'person' | 'agent' | 'key' | 'guest' | 'platform', required
        - `user_id` string, nullable
        - `name` string, nullable
        - `session_id` string
        - `agent_type` string
        - `key_id` string
      - `text` string, nullable, required: One line to show, at most 400 characters: the message, the tool call's summary, the question, the answer, the file path, the artifact name, the connector call, the event's title or name
      - `detail` object, required: The kind's own fields: `role` and `message_id` (message); `tool_name`, `call_id`, `summary`, `status` (`ok`, `error`, or null when no result is recorded) and `message_id` (tool.call); `request_id`, `request_kind`, `options`, `required_user_id` (request.asked); `request_id` (request.answered); `kind`, `value`, `ref` (decision, outcome); `target_user_id` (mention); `assignee_user_id` (assignment); `path`, `version_id`, `size_bytes`, `conflict` (file.changed); `artifact_id`, `name`, `version`, `comment_id`, `parent_id` (artifact.*); `app`, `app_name`, `method`, `host`, `status`, `provider`, `agent_session_id`, and, when the caller's own log holds the call's full reply, `event_id`, `url` and `bodies` (connector.call); `status`, `note_file_id` (meeting.recorded); `role`, `agent_type`, `llm` (session.started). An event's entry carries the event's scalar payload fields, `event_id`, `source`, `surface`, `objects` and `bodies`: each stored body's `GET /v1/events/{id}/body` path by part.
    - `order` 'asc' | 'desc', required: Which way `next_cursor` continues
    - `next_cursor` string, nullable, required: Pass as `cursor` for the next page in the same order; null when nothing is left
    - `truncated` boolean, required: Without `order` or `cursor`: older entries exist (read them with `next_cursor`)

## Other responses

- `default`: Error — { error: { code, message } }

## Changes

- **2026-11-02** `e5e8f0229a99`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/agentsky/apis/agentsky-developer-api/changes/tasks/:id/story/get.md)

---

[API](https://skmtc.dev/agentsky/apis/agentsky-developer-api.md) - [All operations](https://skmtc.dev/agentsky/apis/agentsky-developer-api/llms.txt) - [OpenAPI document](https://skmtc.dev/agentsky/apis/agentsky-developer-api/revisions/0d435187cd55?raw)
