Packages

The AgentScript monorepo is organized as a set of layered packages. Each layer builds on the one below it. Understanding the stack helps you pick the right entry point for your use case.

Architecture

┌──────────────────────────────────────────────────────────┐
│  UI Playground (React + Vite)                             │
│  Monaco editor · graph view · CST explorer · examples    │
├──────────────────────────────────────────────────────────┤
│  Editor Integrations                                      │
│  @sf-agentscript/vscode  ·  @sf-agentscript/monaco        │
├──────────────────────────────────────────────────────────┤
│  LSP Layer                                                │
│  lsp (core) · lsp-server (Node.js) · lsp-browser (Worker)│
├──────────────────────────────────────────────────────────┤
│  SDK  (@sf-agentscript/agentforce)                        │
│  parse · Document · compileSource · parseComponent        │
├──────────────────────────────────────────────────────────┤
│  Compiler  (@sf-agentscript/compiler)                     │
│  AST → Salesforce runtime spec + source maps             │
├──────────────────────────────────────────────────────────┤
│  Dialect Layer                                            │
│  agentscript (base) · agentforce · agentfabric            │
├──────────────────────────────────────────────────────────┤
│  Core Language  (@sf-agentscript/language)                │
│  AST types · scope resolution · linting framework        │
├──────────────────────────────────────────────────────────┤
│  Parsers                                                  │
│  parser-javascript (TypeScript) · parser-tree-sitter (C) │
├──────────────────────────────────────────────────────────┤
│  Foundation  (@sf-agentscript/types)                      │
│  SyntaxNode · Diagnostic · Range — zero dependencies     │
└──────────────────────────────────────────────────────────┘

Packages are published to npm under the @sf-agentscript/* scope. The @agentscript/* names used internally in the monorepo are workspace aliases — they resolve to the same packages.

Foundation Layer

Shared primitive types used across every other package. Zero dependencies — safe to import anywhere.

@sf-agentscript/types
Shared Types
Defines SyntaxNode, Diagnostic, Range, Position, and other primitives shared across all packages. No runtime dependencies.
foundation

Key types

// Position in source
interface Position { line: number; character: number }
interface Range    { start: Position; end: Position }

// Parse/lint diagnostic
interface Diagnostic {
  message:  string
  severity: 'error' | 'warning' | 'info' | 'hint'
  range:    Range
  code?:    string
}

// Raw syntax node from parser
interface SyntaxNode {
  type:     string
  text:     string
  range:    Range
  children: SyntaxNode[]
}

Core Language

@sf-agentscript/parser-javascript
TypeScript Parser
Hand-written recursive descent parser with Pratt expression parsing. Error-tolerant — recovers from syntax errors to enable better IDE support. Pure TypeScript, no native dependencies. Produces a concrete syntax tree (CST).
parser
@sf-agentscript/parser-tree-sitter
Tree-sitter Parser
Declarative Tree-sitter grammar (the source-of-truth grammar). Compiles to a C parser with Node.js native bindings and WASM for browser use. Rebuild required after grammar changes.
parser
@sf-agentscript/parser
Parser Abstraction
Abstraction layer that resolves to parser-javascript by default. Swap to parser-tree-sitter via conditional exports. Consumer code imports from this package — not the parser implementations directly.
parser
@sf-agentscript/language
Language Infrastructure
Core analysis engine. Provides AST types, scope and symbol resolution, the linting framework (18+ passes), and the Language Service API. Dialect-agnostic — all platform-specific logic lives in dialect packages.
core

Parser selection

The JavaScript parser is the default and recommended choice for most use cases. The Tree-sitter parser is the authoritative grammar and is used for syntax highlighting queries:

// Default: resolves to parser-javascript
import { parse } from '@sf-agentscript/parser'

// Explicit tree-sitter (via package.json exports conditions)
// Set "agentscript:parser" = "tree-sitter" in your build config

Dialect Layer

Dialects extend the base schema with platform-specific blocks, fields, and lint rules. Each dialect exports a DialectConfig object that is injected into the parser, language service, and LSP.

@sf-agentscript/agentscript-dialect
Base Dialect
Defines the core AgentScript schema: system, config, variables, actions, start_agent, subagent, reasoning, before_reasoning, after_reasoning, connected_subagent. Base lint rules.
dialect
@sf-agentscript/agentforce-dialect
Agentforce Dialect
Extends the base dialect with Salesforce Agentforce-specific blocks: modality, security, model_config, related_agent, language. Adds topic as an alias for subagent. Includes its own compiler.
dialect
@sf-agentscript/agentfabric-dialect
AgentFabric Dialect
Alternative schema and compiler targeting the AgentFabric runtime. Fully independent lint rules and block definitions.
dialect

Dialect schema structure

Schema definitions use factory functions from @sf-agentscript/language:

import { Block, TypedMap, NamedBlock, CollectionBlock } from '@sf-agentscript/language'

// Fixed-field block: only declared keys are valid
const ConfigBlock = Block('ConfigBlock', {
  agent_name:  StringValue,
  description: StringValue,
})

// Variadic map: any user-defined keys, all same type
const VariablesBlock = TypedMap('VariablesBlock', VariablePropertiesBlock)

// Named block: accepts an instance name (subagent foo:)
const SubagentBlock = NamedBlock('SubagentBlock', {
  description:     StringValue,
  reasoning:       ReasoningBlock,
  before_reasoning: ProcedureBlock,
  after_reasoning:  ProcedureBlock,
})

// Collection: map of named blocks
const ActionsBlock = CollectionBlock(ActionBlock)

Compiler

@sf-agentscript/compiler
AST Compiler
Transforms a parsed AgentScript AST into a Salesforce runtime specification (JSON) with full source-map support for error reporting and debugging. Used by the Agentforce dialect.
compiler
import { compile } from '@sf-agentscript/compiler'

const result = compile(ast, { dialect: agentforceDialect })
console.log(result.spec)   // JSON runtime specification
console.log(result.maps)   // source maps (position → spec location)

SDK — @sf-agentscript/agentforce

The batteries-included SDK. Combines parser, language service, compiler, and dialects into a single import. The recommended entry point for most use cases. Works in Node.js and browsers.

npm install @sf-agentscript/agentforce

parse(source)

Parses and analyzes an AgentScript source string. Returns a Document containing diagnostics, the AST, and mutation methods.

import { parse } from '@sf-agentscript/agentforce'

const doc = parse(`
system:
    instructions: "You are a helpful agent."

start_agent main:
    reasoning:
        instructions: ->
            | Help the user.
`)

doc.hasErrors        // boolean — true if any error-level diagnostics
doc.diagnostics      // Diagnostic[] — all parse, lint, and schema errors
doc.emit()           // string — formatted source (round-trip safe)

Document

The Document class represents a parsed, analyzed agent script with mutation support and undo/redo history:

import { parse } from '@sf-agentscript/agentforce'

const doc = parse(source)

// Read
doc.hasErrors                    // boolean
doc.diagnostics                  // Diagnostic[]
doc.emit()                       // formatted source string

// Mutate (creates new history entry)
doc.set(['config', 'agent_name'], 'UpdatedName')
doc.set(['variables', 'order_id', 'default'], '"ORD-999"')

// History
doc.undo()    // revert last mutation
doc.redo()    // reapply
doc.canUndo   // boolean
doc.canRedo   // boolean

// After mutation
doc.emit()    // reflects the change

compileSource(source)

Parses and compiles a source string to the Salesforce runtime specification in one step:

import { compileSource } from '@sf-agentscript/agentforce'

const result = compileSource(source)

result.spec        // object — JSON runtime specification
result.maps        // source maps
result.diagnostics // compile-time diagnostics (includes parse + lint)

parseComponent() / emitComponent()

Work with individual agent components (subagent blocks, action definitions, etc.) in isolation:

import { parseComponent, emitComponent } from '@sf-agentscript/agentforce'

// Parse a single component block
const component = parseComponent('subagent', `
billing:
    description: "Handles billing"
    reasoning:
        instructions: "Help with billing."
`)

// Emit back to source
const source = emitComponent(component)

LSP Layer

The Language Server Protocol layer provides IDE features for any LSP-compatible editor. All providers are dialect-agnostic — platform logic is injected via config.

@sf-agentscript/lsp
LSP Core
All LSP providers: diagnostics, hover, completions, go-to-definition, find references, rename, document symbols, code actions, semantic tokens. Parser and dialects are injected via config — no platform assumptions.
lsp
@sf-agentscript/lsp-server
Node.js LSP Server
Thin stdio/IPC wrapper over @sf-agentscript/lsp. Ships the agentscript-lsp CLI binary used by the VS Code extension and other editors via their LSP client.
lsp
@sf-agentscript/lsp-browser
Browser LSP Server
Browser LSP server that runs in a Web Worker. Uses the TypeScript parser (no native dependencies). Single-bundle output for IDE-in-browser scenarios like the UI playground.
lsp

LSP capabilities

CapabilityDescription
DiagnosticsParse errors, schema validation, lint warnings, compile errors — all in one pass
HoverType info and documentation for variables, actions, blocks, and built-ins
CompletionsField names, namespace members (@variables.*, @actions.*), block keywords
Go to DefinitionJump to variable or action declaration from any reference
Find ReferencesLocate all uses of a variable, action, or subagent
RenameRefactor identifiers across the entire document
Document SymbolsOutline view showing all blocks and named declarations
Code ActionsQuick-fix suggestions for lint warnings
Semantic TokensTree-sitter query-based syntax highlighting

Dialect detection

The LSP selects the dialect from a comment in the first 10 lines of the file:

# @dialect: agentforce=2.2

Falls back to defaultDialect from the server config, or the first registered dialect.

Editor Integrations

@sf-agentscript/vscode
VS Code Extension
Full VS Code extension for .agent files. Launches agentscript-lsp as a language server and activates all LSP features. Includes syntax highlighting via Tree-sitter highlight queries.
editor
@sf-agentscript/monaco
Monaco Editor Integration
Monaco Editor integration for browser-based editors. Registers the AgentScript language, provides syntax highlighting, hover, and schema resolution via the browser LSP worker. Used by the UI playground.
editor

VS Code setup

The extension is installed from the VS Code marketplace (or .vsix locally). It activates automatically for .agent files and requires no additional configuration:

# Build the extension locally
pnpm build
cd packages/vscode
pnpm package   # produces agentscript-*.vsix

# Install locally
code --install-extension agentscript-*.vsix

Applications

apps/ui
UI Playground
React + Vite browser playground. Monaco editor with full LSP, graph view for visualizing subagent flow, CST/AST explorer, compiled output viewer, dialect switcher, and preloaded examples. Run with pnpm ui:dev at localhost:27002.
app
apps/docs
Docs Site
Docusaurus 3 documentation site. Auto-generated TypeDoc API docs from package source plus manually-authored guides. Run with pnpm docs:dev at localhost:27000. Generate API docs with pnpm docs:typedoc.
app

Building a Custom Dialect

Dialects are plain TypeScript packages that export a DialectConfig. There is no central registry — consumers import dialects directly.

  1. Create the dialect package
    mkdir -p dialect/mydialect/src
    cd dialect/mydialect
    # package.json with @sf-agentscript/language as dependency
  2. Define your schema
    // dialect/mydialect/src/schema.ts
    import { Block, StringValue, BooleanValue } from '@sf-agentscript/language'
    
    export const MyCustomBlock = Block('MyCustomBlock', {
      my_field:    StringValue,
      my_flag:     BooleanValue,
    })
  3. Add lint rules (optional)
    // dialect/mydialect/src/lint/passes/my-rule.ts
    import type { LintPass } from '@sf-agentscript/language'
    
    export const myRule: LintPass = {
      id: 'my-dialect/my-rule',
      run(doc, report) {
        // walk doc.ast, call report() for issues
      }
    }
  4. Export the DialectConfig
    // dialect/mydialect/src/index.ts
    import type { DialectConfig } from '@sf-agentscript/language'
    import { MyCustomBlock } from './schema.js'
    import { myRule } from './lint/passes/my-rule.js'
    
    export const myDialect: DialectConfig = {
      name: 'mydialect',
      version: '1.0',
      blocks: { my_custom: MyCustomBlock },
      lintPasses: [myRule],
    }
  5. Register in consumers

    Import and pass your dialect to the LSP server config, the SDK, or the UI playground's dialect registry. No central registration step needed.

    import { parse } from '@sf-agentscript/agentforce'
    import { myDialect } from './dialect/mydialect/src/index.js'
    
    const doc = parse(source, { dialect: myDialect })

Build & Development

CommandDescription
pnpm buildBuild all packages via Turbo (parallel, incremental)
pnpm devWatch mode for all packages
pnpm testRun all tests (Vitest)
pnpm lintLint all packages (ESLint)
pnpm typecheckType-check all packages
pnpm formatFormat with Prettier
pnpm ui:devRun UI playground at localhost:27002
pnpm docs:devRun docs site at localhost:27000
pnpm docs:typedocGenerate TypeDoc API reference

Toolchain

ToolPurpose
pnpm workspacesMonorepo package management
TurboBuild orchestration — parallel builds, caching
TypeScriptAll packages are fully typed
VitestUnit testing
ESLint + PrettierLinting and formatting
miseToolchain version management (Node.js, tree-sitter CLI)

Repository layout

agentscript/
├── packages/          # Core toolchain packages
│   ├── types/
│   ├── parser-javascript/
│   ├── parser-tree-sitter/
│   ├── parser/
│   ├── language/
│   ├── compiler/
│   ├── agentforce/    # SDK
│   ├── lsp/
│   ├── lsp-server/
│   ├── lsp-browser/
│   ├── vscode/
│   └── monaco/
├── dialect/           # Dialect implementations
│   ├── agentscript/
│   ├── agentforce/
│   └── agentfabric/
├── apps/
│   ├── ui/            # React playground
│   └── docs/          # Docusaurus site
├── SPEC.md            # Formal language specification
└── CONTRIBUTING.md