Skip to main content

JaKtA 1.0: a redesign

· 3 min read

JaKtA 1.0 is a rewrite from the ground up. The BDI model is the same, but the engine, the DSL and the module structure are new — and multiplatform.

Why a new engine​

JaKtA has its own BDI execution engine instead of reusing an existing one, because of two design goals:

  1. to explore paradigm blending of agent-oriented programming, and BDI in particular, with mainstream programming languages, and
  2. to make every aspect of running a BDI system modular and pluggable: reasoning, message passing, concurrency models, and the like.

The DSL is kept apart from the engine, since it is only one possible syntax for specifying BDI multi-agent systems: other languages could be plugged on top of the same engine.

What changed​

  • Kotlin Multiplatform. The core libraries run on the JVM, in JavaScript (browser and Node.js, also on npm as @jakta/*) and natively.
  • A coroutine engine. Each intention is a coroutine and plan bodies are ordinary suspend Kotlin code: call functions, delay, wait for events, and return results from sub-goals.
  • Pluggable knowledge representation. The engine is generic over beliefs and goals. An incarnation fixes them: Prolog terms through 2P-Kt, plain strings, or your own Kotlin types.
  • Skills instead of actions. What an agent can do is a Kotlin object given to its plans through context parameters, checked by the compiler.
  • Nodes instead of environments. Agents live in nodes that deliver perceptions and messages, with Jason-style KQML messaging in the Prolog incarnation.
  • Simulation. The Alchemist incarnation runs JaKtA agents in simulated time.

Before and after​

// JaKtA 0.x
mas {
agent("myAgent") {
goals { achieve("sayHello") }
plans {
+achieve("sayHello") then { execute("print"("Hello, World!")) }
}
}
}.start()

// JaKtA 1.x (Prolog incarnation)
val helloWorldAgent = agent<PrologBelief, PrologGoal, Any> {
embodiedAs { Any() }
hasInitialGoals { !initialGoal { Atom.of("sayHello") } }
hasPlanLibrary {
prologPlan {
adding.goal { matchingGoal { Atom.of("sayHello") } } triggers {
agent.print("Hello, world!")
}
}
}
}

fun main(): Unit = runBlocking {
mas(NodeBuilders.baseNode()) {
node { withAgents(helloWorldAgent) }
}.runLocally()
}

Getting started​

The documentation has been rewritten for 1.x, and the examples now live in the main repository. JaKtA 0.x is deprecated; if you are reading one of our earlier papers, the JaKtA 0.x page collects the old resources. For how JaKtA moved away from Jason, read Jason-like Kotlin Agents.