Files
united-workforce/packages/workflow-util-agent/README.md
T
xingyue e067a2f25a
CI / check (pull_request) Failing after 9m51s
refactor: rebrand npm packages @uncaged/* → @united-workforce/*
Package mapping:
- @uncaged/cli-workflow → @united-workforce/cli
- @uncaged/workflow-protocol → @united-workforce/protocol
- @uncaged/workflow-util → @united-workforce/util
- @uncaged/workflow-util-agent → @united-workforce/util-agent
- @uncaged/workflow-agent-hermes → @united-workforce/agent-hermes
- @uncaged/workflow-agent-claude-code → @united-workforce/agent-claude-code
- @uncaged/workflow-agent-builtin → @united-workforce/agent-builtin
- @uncaged/workflow-dashboard → @united-workforce/dashboard

Changes:
- 8 package.json name + dependency refs
- 82 files: import statements updated
- .changeset/config.json updated
- CLAUDE.md updated
- bunfig.toml restored for preload

CLI command (uwf) and directory names unchanged.

Closes shazhou/united-workforce#8
2026-06-02 20:56:06 +08:00

5.1 KiB

@united-workforce/util-agent

Agent framework — createAgent factory, context builder, frontmatter fast-path, and LLM extract pipeline.

Overview

Layer 2 agent framework. Provides the standard entrypoint for all agent CLIs: parse <thread-id> <role> from argv, load thread/workflow context from CAS, invoke the agent's run/continue functions, validate output via frontmatter fast-path or LLM extract, and write a StepNodePayload to CAS.

Also exports prompt builders, config/storage helpers, and session ID caching for multi-turn agents.

Dependencies: @ocas/core, @ocas/fs, @united-workforce/protocol, @united-workforce/util, dotenv, yaml

Installation

bun add @united-workforce/util-agent

API

All exports come from src/index.ts.

Agent factory

function createAgent(options: AgentOptions): () => Promise<void>

type AgentOptions = {
  name: string;
  run: AgentRunFn;
  continue: AgentContinueFn;
};

type AgentRunFn = (ctx: AgentContext) => Promise<AgentRunResult>;
type AgentContinueFn = (
  sessionId: string,
  message: string,
  store: AgentContext["store"],
) => Promise<AgentRunResult>;

type AgentRunResult = {
  output: string;
  detailHash: string;
  sessionId: string;
};

Agent CLIs call createAgent(...) and invoke the returned function as main().

Context

function buildContext(threadId: ThreadId, role: string): Promise<AgentContext>
function buildContextWithMeta(
  threadId: ThreadId,
  role: string,
): Promise<AgentContext & { meta: BuildContextMeta }>

type AgentContext = ModeratorContext & {
  threadId: ThreadId;
  role: string;
  store: Store;
  workflow: WorkflowPayload;
  outputFormatInstruction: string;
  edgePrompt: string;
  isFirstVisit: boolean;
};

type BuildContextMeta = {
  storageRoot: string;
  store: Store;
  schemas: AgentStore["schemas"];
  headHash: CasRef;
  chain: ChainState;
};

Requires UWF_EDGE_PROMPT in the environment (set by uwf thread step).

Prompt builders

function buildRolePrompt(role: RoleDefinition): string
function buildOutputFormatInstruction(schema: JSONSchema): string
function buildContinuationPrompt(
  steps: StepContext[],
  role: string,
  edgePrompt: string,
  options?: { includeContent?: boolean; quota?: number },
): string

Extract pipeline

function resolveExtractModelAlias(config: WorkflowConfig): ModelAlias
function resolveModel(config: WorkflowConfig, alias: ModelAlias): ResolvedLlmProvider
function extract(
  rawOutput: string,
  outputSchema: CasRef,
  config: WorkflowConfig,
): Promise<ExtractResult>

type ResolvedLlmProvider = { baseUrl: string; apiKey: string; model: string };
type ExtractResult = { value: unknown; hash: CasRef };

Frontmatter fast-path

function tryFrontmatterFastPath(
  rawOutput: string,
  outputSchema: CasRef,
  store: Store,
): Promise<FrontmatterFastPathResult | null>

type FrontmatterFastPathResult = { body: string; outputHash: CasRef };

Session cache

function getCachedSessionId(threadId: ThreadId, role: string): Promise<string | null>
function setCachedSessionId(
  threadId: ThreadId,
  role: string,
  sessionId: string,
): Promise<void>

Config and storage

function getConfigPath(storageRoot: string): string
function getEnvPath(storageRoot: string): string
function resolveStorageRoot(): string
function loadWorkflowConfig(storageRoot: string): Promise<WorkflowConfig>

Usage

import { createAgent, buildRolePrompt } from "@united-workforce/util-agent";
import type { AgentContext, AgentRunResult } from "@united-workforce/util-agent";

async function run(ctx: AgentContext): Promise<AgentRunResult> {
  const prompt = buildRolePrompt(ctx.workflow.roles[ctx.role]!);
  // ... spawn external process, capture output ...
  return { output: markdown, detailHash: "...", sessionId: "..." };
}

async function continueSession(
  sessionId: string,
  message: string,
): Promise<AgentRunResult> {
  // ... continue multi-turn session ...
  return { output: markdown, detailHash: "...", sessionId };
}

export const main = createAgent({ name: "my-agent", run, continue: continueSession });

Internal Structure

src/
├── index.ts
├── run.ts                         createAgent entrypoint
├── context.ts                     Thread chain walk, AgentContext builder
├── extract.ts                     LLM structured extract fallback
├── frontmatter.ts                 Frontmatter fast-path validation
├── build-role-prompt.ts           Role definition → prompt text
├── build-output-format-instruction.ts
├── build-continuation-prompt.ts
├── session-cache.ts               Per-thread/session ID persistence
├── storage.ts                     CAS store, config, threads index
├── schemas.ts                     Agent CAS schema registration
└── types.ts                       AgentContext, AgentOptions, etc.

Configuration

Reads config.yaml and .env from the workflow storage root (~/.uncaged/workflow by default). See @united-workforce/protocol for WorkflowConfig shape. Set via uwf setup.