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

# Threads & objects

> Shared state inside a session: the objects people, workflows and agents read and write, and the threads they talk through.

export const Scope = ({type, href}) => {
  const scopes = {
    workflow: ['the ', 'Workflow', ' blob type', '/blob-types/introduction#workflow'],
    scheduler: ['the ', 'Scheduler', ' blob type', '/blob-types/scheduler/overview'],
    onnx: ['the ', 'ONNX Model', ' blob type', '/blob-types/introduction#onnx'],
    worker: ['', 'blobhub-worker', ', which runs on your machines', '/worker/introduction']
  };
  const scope = scopes[type];
  if (!scope) {
    return <p>Unknown scope: {type}</p>;
  }
  return <p className="text-sm text-gray-600 dark:text-gray-400">
      Provided by {scope[0]}<strong>{scope[1]}</strong>{scope[2]}. · <a href={href || scope[3]}>Reference</a>
    </p>;
};

export const Shot = ({src, alt, caption}) => <Frame caption={caption}>
    <img className="block dark:hidden" src={src} alt={alt} />
    <img className="hidden dark:block" src={src.replace(/\.(png|svg)$/, '.dark.$1')} alt={alt} />
  </Frame>;

<Scope type="workflow" href="/blob-types/workflow/session-objects/introduction" />

A session's state is a set of typed objects, each addressed by a path-shaped alias. A person in the web app, a
workflow's code and an agent on the worker all read and write the same objects through the same API, so they share
work without integration code between them. Three kinds of object hold more than a value: a thread for
conversation, a graph for connected records, and a file for bytes.

## Session objects and aliases

An object's alias is its only key: there is no separate id behind it. The alias is a path, one or more segments
joined by `/`, such as `inbox/thread` or `missions/a1/graph`, so everything belonging to one piece of work can sit
under one prefix. Listing takes a prefix to keep to one subtree, and a delimiter to collapse everything past the
next segment into a single entry, so you walk the namespace one level at a time, the way you list a directory.

Every value starts with a type. Most types are plain values: text, a number, a boolean, a chosen option, a
credential reference, a generative-AI message, or a list of messages. You upload, download and delete a plain value
whole, and an upload replaces it. Thread and graph are envelopes instead: creating one makes a container, and what
goes inside it changes through operations of its own. A file is a simpler envelope around one set of bytes.
Deleting any envelope deletes everything it holds. Every write and delete raises a session event naming the
object's alias and type.

An object's value can name an owner, and a caller can treat that as a claim: create the object only when the alias
is free, or overwrite it only when the stored owner is the caller. That is a check-then-write convention, not a lock.
Every write is an unconditional overwrite, so two callers racing for the same alias can both write, and the last
write wins. The worker's claim on a session is the platform's own example.

## Threads

A thread is a conversation that only grows.
[Posting an item](/blob-types/workflow/operations/post-session-thread-item) is the one change it allows: no item is
ever edited or removed, except all at once when the thread or its session is deleted. Anyone may add and no one may
alter, so a person, a workflow and an agent can post into the same thread without coordinating, each one asking for
what has arrived since it last looked. Items come back a page at a time, oldest or newest first, with a cursor to
continue from.

Each item records who posted it and when, and says what it says in two places:

* **`content`** is for readers: an ordered list of text, JSON and file blocks, which a conversation view renders in
  that order. An item carries up to ten file blocks, each placed where it belongs among the text.
* **`metadata`** is for programs: an arbitrary object for what a consumer needs to act on, such as a tool call's
  arguments, a token count or a question still waiting for an answer.

The thread's own envelope has metadata too, and its `state` field is how work is handed to the
[worker](/general/agents-and-workers). You set it to `pending` to hand the thread to an agent, and to `completed` or
`failed` to end the agent's part; the worker writes back only `active`, once it picks the thread up, and `failed`.
[Threads](/blob-types/workflow/session-objects/thread/introduction) has the item format.

<Shot src="/general/images/threads-and-objects/thread.png" alt="A thread widget with tickets, drafted replies and a held refund" caption="People, workflows and agents add to the same thread; nothing posted is ever rewritten." />

## Graphs

A graph object holds a property graph. A vertex has one or more labels, fixed when it is created, and properties
you can set or clear; an edge has one label and runs from a source vertex to a target. Every element carries a
revision counter that moves on each change.

Changes go in as a batch, and the batch is applied as one transaction: every operation in it takes effect, or none
does. An operation can state the revision it expects its element to be at, and the whole batch is refused if the
element has moved on, so a change you never saw is not silently overwritten. Reading happens on the server, three
ways: paging through every element, listing the neighbours one hop from a set of vertices, or a short traversal
query whose depth, fan-out and result size are capped.

A graph object is not the legacy Graph blob type. It lives in its session, is deleted with it, and is read only
through the operations above, never with SQL.
[Graphs](/blob-types/workflow/session-objects/graph/introduction) has the operations and their caps.

<Shot src="/general/images/threads-and-objects/graph.png" alt="A graph widget showing research sources, claims and themes" caption="A graph object holds vertices and edges that a workflow changes in transactional batches." />

## Files

A file is the one object that holds bytes. Its envelope carries a name, a content type, a size and a checksum,
listed and addressed like any other object, while the bytes are fetched by a read of their own. A file is created
only by its own upload, never by the generic one, and the upload enforces a size cap, the
`workflow.session_file_bytes` [limit](/general/limits#workflow), and an allowlist of content types.

A thread item never carries a file's bytes. It carries a file block naming the file's alias, and posting the item
checks that the alias is a real file in the same session, up to ten per item. Only a thread item's references are
checked: one kept in another object's value or on a graph element is plain JSON, and can outlive the file it names.
Deleting a file deletes its bytes. [Files](/blob-types/workflow/session-objects/file/introduction) lists the allowed
types.

<Shot src="/general/images/threads-and-objects/file.png" alt="A thread item with a report attached as a file" caption="A file is uploaded once and referenced from a thread item by its alias." />

## How people, workflows and agents talk

Three kinds of writer use the same threads and objects, each through the ordinary API:

* **People, in the web app.** A playground's thread widget renders a thread's items as a conversation and posts
  new ones from its composer. You attach files from the `+` menu, by dragging, or by pasting, and each file lands
  where you placed it in the text. [Playgrounds](/general/playgrounds) covers the widgets.
* **Workflows, from code.** A `logic.code` component reaches its own session through helper calls: read, write and
  list objects, post to and page through threads, change and query graphs. They are the same commands any other
  client sends, bound to the run's session. [Code Component](/blob-types/workflow/workflows/component-code) lists
  them.
* **Agents, through the worker.** The worker runs a coding agent's turns against a thread: it reads the new items,
  runs a turn, and posts the agent's output back as items, with the files the agent produced as file blocks. When
  the agent needs an answer, the question arrives as an item and the person's reply goes back the same way.
  [Agents & workers](/general/agents-and-workers) and the worker's [concepts](/worker/concepts) cover it.

None of the three needs to know about the others. Each posts to the thread, reads what has arrived since its own
cursor, and leaves everything already there as it was.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.