Skip to Content
Agentlang is open source now!
ReferenceBusiness Logic

Business Logic

Agentlang workflows define the dynamic behavior of applications — how data flows between entities, reacts to events, and integrates with external systems.

They are declarative, reactive, and can mix Agentlang patterns with embedded JavaScript for flexibility.


1. Overview

A workflow defines a named unit of logic, triggered manually or by system events. A workflow can:

  • Create, update, or delete entities.
  • React to CRUD events.
  • Execute conditional or iterative logic.
  • Call external JavaScript functions or log output.
  • Send messages or trigger LLM-powered agents.

2. Workflow Definition

Basic Syntax

workflow myWorkflow { {Entity {attribute value, ...}} }

Each statement inside a workflow is a pattern, defining what to create, update, or delete.


3. CRUD Patterns

Agentlang supports creating or updating entities using a simple pattern-based syntax:

{EntityName {attribute value, ...}}

Examples

{Student {id 1, name "John"}} // a new student instance is created {Teacher {employeeId 1001, subject "Math"}} // a new teacher instance is created

4. Query Expressions

Agentlang supports querying entities within workflows using ? to denote conditions.

Example

{Student {id? 101}} @as [student]

The above retrieves the Student entity whose id equals 101. You can use queried values in later statements using the alias binding student, as in student.name.

To query all instances of an entity, attach ? to the entity name and provide no attributes:

{Student? {}}

The default query operator is = (is-equals) which need not be specified. You can attach other comparison operators to ?. For instance, to query all students who is older than 10 years:

{Student {age?> 10}}

The full list of query-operators:

=, <>, !=, <, <=, >, >=, in, like, between

Some examples:

{Student {age?between [10, 15]}} {Student {name?like "Mat%"}}

4.1 Query and Update

An update operation is combined with a query.

Example:

{Student {id? "101", age age + 1}} // increment the age of the student with id 101

5. Conditional and Iterative Flow

5.1 Conditional Execution

if (condition) { ... } else { ... }

Example

if (Student.grade > 80) { console.log("Excellent student") }

5.2 Iteration

Agentlang workflows can loop over lists or query results:

for (s in {Student {}}) { console.log(s.name) }

This iterates through all students.


6. Event Workflows

Workflows are triggered by events, which may be explicitly defined.

Example

event createStudent { id String, name String } workflow createStudent { { Student { id createStudent.id, name createStudent.name, email createStudent.name + createStudent.id + "@school.com" } } @as s; console.log("Student created: " + s.name); s }

A workflow is triggered when an instance of the event is created:

{ createStudent { id "101", name "Joe" } }

A workflow can also be triggered via HTTP. But for this the event or workflow must be declared as @public.

@public event createStudent { id String, name String }

Invoking the event via an HTTP POST:

curl -X POST http://localhost:8080/school.core/createStudent \ -H 'Content-Type: application/json' \ -d '{"id": "102", "name": "Mary"}'

7. Extended Workflow Capabilities

7.1 Delete and Upsert Patterns

Delete Pattern

delete {E {id? 1}}

Deletes the entity E where id equals 1.

Purge Pattern

The delete pattern only soft-deletes an instance. To permanently remove an instance from the store use purge.

purge {E {id? 1}}

Upsert Pattern

{E {id 1, v 10}, @upsert}

Updates entity E if id=1 exists, otherwise creates a new one.

OperationBehavior
deleteRemoves entities matching a query
@upsertUpdates if exists, inserts otherwise

7.2 Pre/Post CRUD Workflows

Workflows can hook into CRUD lifecycle events using @before or @after.

Syntax

workflow @before <op>:<Entity> { ... } workflow @after <op>:<Entity> { ... }

Example

entity E { id Int @id, v Int } entity F { id Int @id, w Int } workflow @after create:E { {F {id? this.id, w PrePostEvents/E.v * 100}} } workflow @before delete:E { delete {F {id? this.id}} }
HookTimingUse Case
@before createBefore insertionValidation, initialization
@after createAfter insertionCascade updates
@before updateBefore modificationVersion check
@after updateAfter modificationTrigger notifications
@before deleteBefore deletionCleanup child entities
@after deleteAfter deletionAudit trail

Special Variables

VariableMeaning
thisRefers to the current entity instance
<ModuleName>/<EntityName>Refers to other entities within the workflow

7.3 JavaScript Integration

Agentlang allows you to import and call JavaScript modules for procedural or external logic.

Import Syntax

import "<path-to-js>" @as <alias>

Example

module acme.core import "emailClient.js" @as email workflow SendMail { console.log("sending email to " + SendMail.email) email.sendMail(SendMail.email, SendMail.body) }
  • emailClient.js should export callable JS functions.
  • Workflows can use JS built-ins like console.log.

Example with Return Values

import "textUtils.js" @as text workflow NormalizeAndSave { text.normalize(NormalizeAndSave.name) @as normalizedName; {Person {name normalizedName}} }

This normalizes a name using an external JS function before saving it.

To wait for an asynchronous function:

workflow readEmail { await email.read(readEmail.address) }

Execution Model

  • JavaScript runs in a sandboxed context within the Agentlang runtime.
  • Functions can be synchronous or asynchronous.
  • Return values can be used in subsequent workflow patterns.

7.4 Summary

FeatureDescription
delete patternRemoves entities matching a query
upsert patternMerges entity state atomically
@before/@after workflowsLifecycle hooks for entities
thisRefers to the triggering entity instance
import JS modulesIntegrate with custom logic
console.logBuilt-in logging
let variablesLocal value bindings inside workflows

Example — Combined Features

module acme.school import "notify.js" @as notify entity Student { id Int @id, name String, grade String } entity ReportCard { id Int @id, studentId Int, score Int } workflow @after create:ReportCard { if (this.score < 40) { notify.send("Alert: " + this.studentId + " has failed.") } }

Last updated on