Incomplete information about Kappa trace file format

General structure

Click to see the empty trace obtained by running the empty model.


It is nearly valid JSON. It is not because the order of the fields in the top object (dict,model and trace) is fixed and that's forbidden by the JSON specification.

Also, as described later, the "steps" in the trace are represented in a compact format (using arrays for records and numbers for enumerate types) instead of the one you would normally expect (using respectively objects and strings). The purpose of the dict field is exactly to do the correspondance.

In order to use KaStor, you need to fill:

Agent signature

The field signatures is also a kind of dictionary. It gives the name of agent types, sites and internal states of the model. In the rest of the file, references to agent type, site and internal state are made by their "id" in this dictionary

Let's pretend an example is enough to specify its format. The Kappa signature

%agent: C(c1 c2 c3 c4)
%agent: O(o1 o2)
%agent: H(h{p d t})

is represented by


The 2 extra null arguments of the decl of a site (after the declaration of the internal states) have to be present but they don't matter here.

Rule names

The field ast_rules is the table of the rules of the model. Each element is a pair (rule name, rule content). The content does not matter here as soon as a name is provided so the "content" of the can be duplicated everywhere as the fake content of the rule. Again, in the "steps" of the trace rules are identified by their id in this table.


As an example, If your model has 2 rules "foo" and "bar", your trace file will contain:

"ast_rules": [


Given that we use the compact representation described above,here is the top down description (written in OCaml type declaration syntax)

type trace = step list
type step =
  | Subs of int * int
  | Rule of int * event * simulation_info
  | Pert of string * event * simulation_info
  | Init of action list
  | Obs of string * test list list * simulation_info
  | Dummy  of string
Subs and Dummy
are for internal (debugging) use only.
represent the application of a rule. Its first argument is the id of the rule (in the .model.ast_rule table) of the rule.
represents the application of a perturbation. Its first argument is a name for the perturbation.
describe the introduction of some species at the beginning of the simulation
mark the appearence of a pattern of interrest. Its first argument is a name for this "observable". Its second argument is a list of list of tests because they are grouped connected component by connected component. 99% of the time it is a list of 1 element as nearly only connected patterns are tracked...
type simulation_info = {
  story_id: int ;
  story_time: float ;
  story_event: int ;
  profiling_info: null ;
type event = {
  tests : test list list;
  (** The tests written in the rule (connected component by connected component) *)
  actions : action list; (** The modifications written in the rule *)
  side_effects_src : (site * binding_state) list
  (** the site of the agents mentioned in the rule where there is a side
    effects *);
  side_effects_dst : site list
  (** the site of agents not mentionned in the rule that have been freed
    by side effect *);
  connectivity_tests : test list;
  (** witness that patterns where connected (Only in unary instances of molecular rule. An empty list in any other case) *)
type action =
  | Create of agent * (int * int option) list
  | Mod_internal of site * int (** internal state id *)
  | Bind of site * site
  | Bind_to of site * site
  | Free of site
  | Remove of agent

When an agent is Created, you must introduce all its sites as either Free or Bind_to as well as all internal states (when they exists) using Mod_internal. Beware of Createing both extremities of a created edge before putting the Bind_to.

When the action is to link 2 sites already present in the soup, Bind is used and not Bind_to.

The second argument of the constructor Created is a part of the technical debt of the Kappa source code. You have to give the list of the sites and duplicate the internal state in which the site are introduced (when they is one). Yes, this is as dumb as writing [[0,null],[1,null],[2,null]] each time you introduce an agent with 3 sites (and no internal state)... Any question must be asked to Jérôme Feret :-)

type test =
  | Is_Here of agent
  | Has_Internal of site * int (** internal state id *)
  | Is_Free of site
  | Is_Bound of site
  | Has_Binding_type of site * binding_type
  | Is_Bound_to of site * site

When you test some site of an agent, you must have tested before Is_Here of that agent...

type binding_state =
  | ANY
  | FREE
  | BOUND_TYPE of binding_type
  | BOUND_to of site
type site = agent * int (** site id *)
type agent = int (** agent id *) * int (** agent type id *)
type binding_type = int (** agent type id *) * int (** site id *)