Skip to content

ConversationHandle

Invocation-bound conversation handles: what a task phase (TaskRuntime.conversation) or a tool execution (ToolCall.conversation) uses to drive another conversation, such as a subagent’s. Every operation, and every operation of a submission it returns, fails with InvocationEnded once the invocation that obtained the handle has ended, and an operation in flight when it ends is interrupted with that error. Work already admitted stays durable.

import { type Ids, TaskRuntime } from "@effective-harness/core"
import * as Effect from "effect/Effect"
import * as Option from "effect/Option"
declare const childId: Ids.ConversationId
const program = Effect.gen(function* () {
const child = yield* TaskRuntime.conversation(childId)
if (Option.isSome(child)) {
const submission = yield* child.value.submit({ type: "input", content: "Summarize the plot" })
const settled = yield* submission.wait
}
})

Since v0.0.0


Signature

export interface ConversationHandle {
readonly id: ConversationId
/**
* Admit an input, as `Conversation.submit`. The admission is checked on the commit line: it fails with
* `InvocationEnded` (or `TaskRejected`, once the invoking task is abort-marked) instead of landing after its
* invocation stopped.
*/
readonly submit: (
draft: InputDraft
) => Effect.Effect<SubmissionHandle, CommitError | ConversationBusy | InvocationEnded | SchedulerClosed>
/** Withdraw the queued inputs, abort the ordinary work and wait until idle, as `Conversation.abort`. */
readonly abort: (options?: {
readonly background?: boolean
}) => Effect.Effect<void, CommitError | SchedulerClosed | InvocationEnded>
/** Wait until the conversation has no live non-background work. */
readonly waitForIdle: Effect.Effect<void, SchedulerClosed | InvocationEnded>
}

Source

Since v0.0.0

A user input; passive entries are written with ordinary transaction writes instead.

Signature

type InputDraft = Extract<SubmissionDraft, { readonly type: "input" }>

Source

Since v0.0.0

An admitted submission, bound to the invocation that made it.

Signature

export interface SubmissionHandle {
readonly id: SubmissionId
/** The committed record; see `Submission.status`. */
readonly status: Effect.Effect<
SubmissionRecord,
SubmissionNotFound | StorageFailure | SessionPoisoned | InvocationEnded
>
/** Wait until it settles; see `Submission.wait`. */
readonly wait: Effect.Effect<Settled, SubmissionNotFound | StorageFailure | SessionPoisoned | InvocationEnded>
/** Withdraw it while it is queued; see `Submission.abort`. */
readonly abort: Effect.Effect<
"aborted" | "already_placed" | "settled",
SubmissionNotFound | CommitError | InvocationEnded
>
}

Source

Since v0.0.0

How the scheduler’s handles admit and follow submissions. The Harness supplies it; a scheduler without one gives handles whose submit dies.

Signature

export interface Submitter {
/** Admit an input in the current commit (`Tx` provided), as `Conversation.submit` does in its own. */
readonly admit: (
conversationId: ConversationId,
draft: InputDraft
) => Effect.Effect<SubmissionId, CommitError | ConversationBusy, Tx>
readonly status: (
id: SubmissionId
) => Effect.Effect<SubmissionRecord, SubmissionNotFound | StorageFailure | SessionPoisoned>
readonly wait: (id: SubmissionId) => Effect.Effect<Settled, SubmissionNotFound | StorageFailure | SessionPoisoned>
readonly abort: (
id: SubmissionId
) => Effect.Effect<"aborted" | "already_placed" | "settled", SubmissionNotFound | CommitError>
}

Source

Since v0.0.0