Skip to content

Models

Ports, nodes, workflows, traces and scores.

models

Canonical data models for a Science ADK research project.

Every model here maps 1:1 onto a durable file on disk. There is no hidden state or external database dependency: the files in research/ represent the complete empirical truth.

Port dataclass

Port(name, type='any', description='', required=True)

A single typed input or output port of an agent.

Attributes:

Name Type Description
name str

The unique name of the port on this agent.

type str

Data type of the port (must be one of PORT_TYPES).

description str

Explanation of what this port carries.

required bool

Whether a value is strictly required on this port.

from_dict classmethod

from_dict(data)

Constructs a Port from a dictionary or string shorthand.

Parameters:

Name Type Description Default
data dict[str, Any] | str

Dictionary containing port specification or string port name.

required

Returns:

Type Description
Port

A new Port instance.

Source code in python/src/science_adk/models.py
@classmethod
def from_dict(cls, data: dict[str, Any] | str) -> Port:
    """Constructs a Port from a dictionary or string shorthand.

    Args:
      data: Dictionary containing port specification or string port name.

    Returns:
      A new Port instance.
    """
    if isinstance(data, str):
        return cls(name=data)
    return cls(
        name=data["name"],
        type=data.get("type", "any"),
        description=data.get("description", ""),
        required=bool(data.get("required", True)),
    )

to_dict

to_dict()

Serializes the Port to a dictionary.

Source code in python/src/science_adk/models.py
def to_dict(self) -> dict[str, Any]:
    """Serializes the Port to a dictionary."""
    return asdict(self)

Ports dataclass

Ports(inputs=list(), outputs=list())

The complete input and output port surface of an agent.

Attributes:

Name Type Description
inputs list[Port]

List of declared input ports.

outputs list[Port]

List of declared output ports.

required_inputs property

required_inputs

Returns all input ports marked as required.

input

input(name)

Retrieves an input port by name, or None if not found.

Source code in python/src/science_adk/models.py
def input(self, name: str) -> Port | None:
    """Retrieves an input port by name, or None if not found."""
    return next((p for p in self.inputs if p.name == name), None)

output

output(name)

Retrieves an output port by name, or None if not found.

Source code in python/src/science_adk/models.py
def output(self, name: str) -> Port | None:
    """Retrieves an output port by name, or None if not found."""
    return next((p for p in self.outputs if p.name == name), None)

from_dict classmethod

from_dict(data)

Constructs Ports from dictionary data.

Parameters:

Name Type Description Default
data dict[str, Any] | None

Dictionary with 'inputs' and 'outputs' lists.

required

Returns:

Type Description
Ports

A new Ports instance.

Source code in python/src/science_adk/models.py
@classmethod
def from_dict(cls, data: dict[str, Any] | None) -> Ports:
    """Constructs Ports from dictionary data.

    Args:
      data: Dictionary with 'inputs' and 'outputs' lists.

    Returns:
      A new Ports instance.
    """
    data = data or {}
    return cls(
        inputs=[Port.from_dict(p) for p in data.get("inputs", [])],
        outputs=[Port.from_dict(p) for p in data.get("outputs", [])],
    )

to_dict

to_dict()

Serializes the Ports instance to a dictionary.

Source code in python/src/science_adk/models.py
def to_dict(self) -> dict[str, Any]:
    """Serializes the Ports instance to a dictionary."""
    return {
        "inputs": [p.to_dict() for p in self.inputs],
        "outputs": [p.to_dict() for p in self.outputs],
    }

Node dataclass

Node(id, name, kind='algorithm', purpose='', ports=Ports(), module='', tools=list(), params=dict(), workflow='')

One step of an experiment: a named agent with a typed port surface.

Attributes:

Name Type Description
id str

Unique identifier of the node within the workflow DAG.

name str

Human-readable name for the node.

kind str

The primitive agent kind (must be one of AGENT_KINDS).

purpose str

Description of what this node does and why.

ports Ports

Declared input and output ports.

module str

Path to the Python file implementing the agent.

tools list[str]

Advisory list of tools this agent may call.

params dict[str, Any]

Static parameters passed to the agent.

workflow str

For composite agents, the path to the nested workflow.

from_dict classmethod

from_dict(data)

Constructs a Node from dictionary data.

Source code in python/src/science_adk/models.py
@classmethod
def from_dict(cls, data: dict[str, Any]) -> Node:
    """Constructs a Node from dictionary data."""
    return cls(
        id=data["id"],
        name=data.get("name", data["id"]),
        kind=data.get("kind", "algorithm"),
        purpose=data.get("purpose", ""),
        ports=Ports.from_dict(data.get("ports")),
        module=data.get("module", ""),
        tools=list(data.get("tools", [])),
        params=dict(data.get("params", {})),
        workflow=data.get("workflow", ""),
    )

to_dict

to_dict()

Serializes the Node instance to a dictionary.

Source code in python/src/science_adk/models.py
def to_dict(self) -> dict[str, Any]:
    """Serializes the Node instance to a dictionary."""
    return _drop_none(
        {
            "id": self.id,
            "name": self.name,
            "kind": self.kind,
            "purpose": self.purpose,
            "ports": self.ports.to_dict(),
            "module": self.module or None,
            "tools": self.tools or None,
            "params": self.params or None,
            "workflow": self.workflow or None,
        }
    )

Edge dataclass

Edge(source, source_port, target, target_port)

A typed connection carrying an output port into an input port.

Attributes:

Name Type Description
source str

Source node id.

source_port str

Name of the output port on the source node.

target str

Target node id.

target_port str

Name of the input port on the target node.

from_dict classmethod

from_dict(data)

Constructs an Edge from dictionary data.

Source code in python/src/science_adk/models.py
@classmethod
def from_dict(cls, data: dict[str, Any]) -> Edge:
    """Constructs an Edge from dictionary data."""
    return cls(
        source=data["source"],
        source_port=data["source_port"],
        target=data["target"],
        target_port=data["target_port"],
    )

to_dict

to_dict()

Serializes the Edge to a dictionary.

Source code in python/src/science_adk/models.py
def to_dict(self) -> dict[str, Any]:
    """Serializes the Edge to a dictionary."""
    return asdict(self)

Workflow dataclass

Workflow(name='', description='', nodes=list(), edges=list(), created_at=utcnow())

The experiment DAG: what runs, in what order, carrying what data.

Attributes:

Name Type Description
name str

Descriptive name of the workflow.

description str

Summary of the experiment pipeline.

nodes list[Node]

List of nodes in the DAG.

edges list[Edge]

List of edges connecting nodes.

created_at str

ISO-8601 creation timestamp.

node

node(node_id)

Finds a node by its ID.

Source code in python/src/science_adk/models.py
def node(self, node_id: str) -> Node | None:
    """Finds a node by its ID."""
    return next((n for n in self.nodes if n.id == node_id), None)

parents

parents(node_id)

Returns sorted list of parent node IDs that precede node_id.

Source code in python/src/science_adk/models.py
def parents(self, node_id: str) -> list[str]:
    """Returns sorted list of parent node IDs that precede node_id."""
    return sorted({e.source for e in self.edges if e.target == node_id})

children

children(node_id)

Returns sorted list of child node IDs that consume output from node_id.

Source code in python/src/science_adk/models.py
def children(self, node_id: str) -> list[str]:
    """Returns sorted list of child node IDs that consume output from node_id."""
    return sorted({e.target for e in self.edges if e.source == node_id})

descendants

descendants(node_id)

Returns all node IDs transitively downstream of node_id.

Source code in python/src/science_adk/models.py
def descendants(self, node_id: str) -> set[str]:
    """Returns all node IDs transitively downstream of node_id."""
    seen: set[str] = set()
    stack = list(self.children(node_id))
    while stack:
        current = stack.pop()
        if current in seen:
            continue
        seen.add(current)
        stack.extend(self.children(current))
    return seen

terminal_nodes

terminal_nodes()

Returns node IDs that produce terminal experiment outputs.

Source code in python/src/science_adk/models.py
def terminal_nodes(self) -> list[str]:
    """Returns node IDs that produce terminal experiment outputs."""
    return [n.id for n in self.nodes if not self.children(n.id)]

from_dict classmethod

from_dict(data)

Constructs a Workflow from dictionary data.

Source code in python/src/science_adk/models.py
@classmethod
def from_dict(cls, data: dict[str, Any]) -> Workflow:
    """Constructs a Workflow from dictionary data."""
    return cls(
        name=data.get("name", ""),
        description=data.get("description", ""),
        nodes=[Node.from_dict(n) for n in data.get("nodes", [])],
        edges=[Edge.from_dict(e) for e in data.get("edges", [])],
        created_at=data.get("created_at", utcnow()),
    )

to_dict

to_dict()

Serializes the Workflow to a dictionary.

Source code in python/src/science_adk/models.py
def to_dict(self) -> dict[str, Any]:
    """Serializes the Workflow to a dictionary."""
    return {
        "name": self.name,
        "description": self.description,
        "created_at": self.created_at,
        "nodes": [n.to_dict() for n in self.nodes],
        "edges": [e.to_dict() for e in self.edges],
    }

NodeRun dataclass

NodeRun(node_id, state='pending', started_at='', finished_at='', duration_s=0.0, outputs=dict(), logs=list(), error='', traceback='', provenance=dict(), fingerprint='')

The execution record of one node.

Attributes:

Name Type Description
node_id str

Identifier of the executing node.

state str

Execution status (pending, running, passed, failed, cached).

started_at str

ISO-8601 execution start timestamp.

finished_at str

ISO-8601 execution finish timestamp.

duration_s float

Total run duration in seconds.

outputs dict[str, Any]

Map of output port names to values or dataset references.

logs list[str]

Informational log messages recorded during execution.

error str

Error message string if execution failed.

traceback str

Exception traceback if execution failed.

provenance dict[str, list[dict[str, Any]]]

Machine-recorded ingress and tool-call evidence.

fingerprint str

Execution cache hash (code + inputs + parameters).

from_dict classmethod

from_dict(data)

Constructs a NodeRun from dictionary data.

Source code in python/src/science_adk/models.py
@classmethod
def from_dict(cls, data: dict[str, Any]) -> NodeRun:
    """Constructs a NodeRun from dictionary data."""
    return cls(
        node_id=data["node_id"],
        state=data.get("state", "pending"),
        started_at=data.get("started_at", ""),
        finished_at=data.get("finished_at", ""),
        duration_s=float(data.get("duration_s", 0.0)),
        outputs=dict(data.get("outputs", {})),
        logs=list(data.get("logs", [])),
        error=data.get("error", ""),
        traceback=data.get("traceback", ""),
        provenance=dict(data.get("provenance", {})),
        fingerprint=data.get("fingerprint", ""),
    )

to_dict

to_dict()

Serializes the NodeRun to a dictionary.

Source code in python/src/science_adk/models.py
def to_dict(self) -> dict[str, Any]:
    """Serializes the NodeRun to a dictionary."""
    return asdict(self)

Trace dataclass

Trace(run_id, experiment='', state='pending', started_at=utcnow(), finished_at='', duration_s=0.0, nodes=list(), error='')

The complete record of one workflow execution run.

Attributes:

Name Type Description
run_id str

Unique run identifier.

experiment str

Experiment identifier.

state str

Overall workflow state.

started_at str

ISO-8601 start timestamp.

finished_at str

ISO-8601 finish timestamp.

duration_s float

Total execution duration in seconds.

nodes list[NodeRun]

List of NodeRun records.

error str

Top-level error message if run aborted.

failed_nodes property

failed_nodes

Returns all NodeRun instances that failed.

ok property

ok

Returns True if the workflow completed successfully.

node

node(node_id)

Retrieves a NodeRun by node ID.

Source code in python/src/science_adk/models.py
def node(self, node_id: str) -> NodeRun | None:
    """Retrieves a NodeRun by node ID."""
    return next((n for n in self.nodes if n.node_id == node_id), None)

from_dict classmethod

from_dict(data)

Constructs a Trace from dictionary data.

Source code in python/src/science_adk/models.py
@classmethod
def from_dict(cls, data: dict[str, Any]) -> Trace:
    """Constructs a Trace from dictionary data."""
    return cls(
        run_id=data["run_id"],
        experiment=data.get("experiment", ""),
        state=data.get("state", "pending"),
        started_at=data.get("started_at", utcnow()),
        finished_at=data.get("finished_at", ""),
        duration_s=float(data.get("duration_s", 0.0)),
        nodes=[NodeRun.from_dict(n) for n in data.get("nodes", [])],
        error=data.get("error", ""),
    )

to_dict

to_dict()

Serializes the Trace to a dictionary.

Source code in python/src/science_adk/models.py
def to_dict(self) -> dict[str, Any]:
    """Serializes the Trace to a dictionary."""
    return {
        "run_id": self.run_id,
        "experiment": self.experiment,
        "state": self.state,
        "started_at": self.started_at,
        "finished_at": self.finished_at,
        "duration_s": self.duration_s,
        "error": self.error,
        "nodes": [n.to_dict() for n in self.nodes],
    }

Gate dataclass

Gate(name, passed, detail='')

One deterministic pass/fail check performed by the engine.

Attributes:

Name Type Description
name str

Name of the integrity check.

passed bool

Whether the check passed.

detail str

Explanation or supporting context.

to_dict

to_dict()

Serializes the Gate to a dictionary.

Source code in python/src/science_adk/models.py
def to_dict(self) -> dict[str, Any]:
    """Serializes the Gate to a dictionary."""
    return asdict(self)

from_dict classmethod

from_dict(data)

Constructs a Gate from dictionary data.

Source code in python/src/science_adk/models.py
@classmethod
def from_dict(cls, data: dict[str, Any]) -> Gate:
    """Constructs a Gate from dictionary data."""
    return cls(
        name=data["name"],
        passed=bool(data.get("passed", False)),
        detail=data.get("detail", ""),
    )

Score dataclass

Score(run_id, gates=list(), pillars=dict(), rationale='', target_metric='', target_value=None, observed_value=None, audited_at='')

The evaluation verdict on one run.

Attributes:

Name Type Description
run_id str

Unique run identifier.

gates list[Gate]

List of deterministic Gate results.

pillars dict[str, float]

Judgement pillar scores (in [0, 1]).

rationale str

Written audit rationale.

target_metric str

Name of the target metric.

target_value float | None

Goal threshold target.

observed_value float | None

Empirically measured value.

audited_at str

ISO-8601 audit timestamp.

gates_passed property

gates_passed

Returns True if all deterministic gates passed.

failed_gates property

failed_gates

Returns all failed gates.

audited property

audited

Returns True if an audit verdict has been recorded.

value property

value

Calculates overall score in [0.0, 1.0]. Returns 0.0 if gates fail.

meets_target property

meets_target

Returns True if observed value meets or exceeds target value.

from_dict classmethod

from_dict(data)

Constructs a Score from dictionary data.

Source code in python/src/science_adk/models.py
@classmethod
def from_dict(cls, data: dict[str, Any]) -> Score:
    """Constructs a Score from dictionary data."""
    return cls(
        run_id=data["run_id"],
        gates=[Gate.from_dict(g) for g in data.get("gates", [])],
        pillars={k: float(v) for k, v in (data.get("pillars") or {}).items()},
        rationale=data.get("rationale", ""),
        target_metric=data.get("target_metric", ""),
        target_value=data.get("target_value"),
        observed_value=data.get("observed_value"),
        audited_at=data.get("audited_at", ""),
    )

to_dict

to_dict()

Serializes the Score to a dictionary.

Source code in python/src/science_adk/models.py
def to_dict(self) -> dict[str, Any]:
    """Serializes the Score to a dictionary."""
    return _drop_none(
        {
            "run_id": self.run_id,
            "value": self.value,
            "gates_passed": self.gates_passed,
            "audited": self.audited,
            "gates": [g.to_dict() for g in self.gates],
            "pillars": self.pillars or None,
            "rationale": self.rationale or None,
            "target_metric": self.target_metric or None,
            "target_value": self.target_value,
            "observed_value": self.observed_value,
            "audited_at": self.audited_at or None,
        }
    )

Goal dataclass

Goal(question='', background='', target_metric='', target_value=None, constraints=list(), created_at=utcnow())

The overarching research question, success metric, and constraints.

Attributes:

Name Type Description
question str

The scientific question under investigation.

background str

Contextual background and motivation.

target_metric str

Quantitative evaluation metric name.

target_value float | None

Success threshold for the target metric.

constraints list[str]

List of experimental or methodological constraints.

created_at str

ISO-8601 creation timestamp.

from_dict classmethod

from_dict(data)

Constructs a Goal from dictionary data.

Source code in python/src/science_adk/models.py
@classmethod
def from_dict(cls, data: dict[str, Any]) -> Goal:
    """Constructs a Goal from dictionary data."""
    return cls(
        question=data.get("question", ""),
        background=data.get("background", ""),
        target_metric=data.get("target_metric", ""),
        target_value=data.get("target_value"),
        constraints=list(data.get("constraints", [])),
        created_at=data.get("created_at", utcnow()),
    )

to_dict

to_dict()

Serializes the Goal to a dictionary.

Source code in python/src/science_adk/models.py
def to_dict(self) -> dict[str, Any]:
    """Serializes the Goal to a dictionary."""
    return _drop_none(asdict(self))

Experiment dataclass

Experiment(id, hypothesis='', rationale='', parent='', generation=0, status='draft', best_run='', best_score=None, created_at=utcnow())

One testable hypothesis and its lineage.

Attributes:

Name Type Description
id str

Unique experiment identifier (e.g., '001-nonlinear-oscillator').

hypothesis str

Precise testable claim.

rationale str

Empirical justification for why this hypothesis was chosen.

parent str

Parent experiment ID in the hypothesis tree.

generation int

Tree depth level of this experiment.

status str

Current status (draft, ready, run, superseded, abandoned).

best_run str

Run ID of the highest scoring run.

best_score float | None

Highest score achieved.

created_at str

ISO-8601 creation timestamp.

from_dict classmethod

from_dict(data)

Constructs an Experiment from dictionary data.

Source code in python/src/science_adk/models.py
@classmethod
def from_dict(cls, data: dict[str, Any]) -> Experiment:
    """Constructs an Experiment from dictionary data."""
    return cls(
        id=data["id"],
        hypothesis=data.get("hypothesis", ""),
        rationale=data.get("rationale", ""),
        parent=data.get("parent", ""),
        generation=int(data.get("generation", 0)),
        status=data.get("status", "draft"),
        best_run=data.get("best_run", ""),
        best_score=data.get("best_score"),
        created_at=data.get("created_at", utcnow()),
    )

to_dict

to_dict()

Serializes the Experiment to a dictionary.

Source code in python/src/science_adk/models.py
def to_dict(self) -> dict[str, Any]:
    """Serializes the Experiment to a dictionary."""
    return _drop_none(asdict(self))

Learning dataclass

Learning(insight, evidence='', experiment='', run_id='', created_at=utcnow())

An empirically validated insight backed by run evidence.

Attributes:

Name Type Description
insight str

The empirical finding or generalization.

evidence str

Specific runs or measurements demonstrating the finding.

experiment str

Experiment identifier where the finding was made.

run_id str

Run identifier of the supporting run.

created_at str

ISO-8601 creation timestamp.

from_dict classmethod

from_dict(data)

Constructs a Learning from dictionary data.

Source code in python/src/science_adk/models.py
@classmethod
def from_dict(cls, data: dict[str, Any]) -> Learning:
    """Constructs a Learning from dictionary data."""
    return cls(
        insight=data["insight"],
        evidence=data.get("evidence", ""),
        experiment=data.get("experiment", ""),
        run_id=data.get("run_id", ""),
        created_at=data.get("created_at", utcnow()),
    )

to_dict

to_dict()

Serializes the Learning to a dictionary.

Source code in python/src/science_adk/models.py
def to_dict(self) -> dict[str, Any]:
    """Serializes the Learning to a dictionary."""
    return _drop_none(asdict(self))

utcnow

utcnow()

Returns an ISO-8601 UTC timestamp string.

Source code in python/src/science_adk/models.py
def utcnow() -> str:
    """Returns an ISO-8601 UTC timestamp string."""
    return datetime.now(timezone.utc).isoformat(timespec="seconds")

slugify

slugify(text, max_length=48)

Transforms text into a filesystem- and git-friendly slug.

Parameters:

Name Type Description Default
text str

The source text string.

required
max_length int

Maximum allowed length of the slug.

48

Returns:

Type Description
str

A normalized lowercase slug string.

Source code in python/src/science_adk/models.py
def slugify(text: str, max_length: int = 48) -> str:
    """Transforms text into a filesystem- and git-friendly slug.

    Args:
      text: The source text string.
      max_length: Maximum allowed length of the slug.

    Returns:
      A normalized lowercase slug string.
    """
    slug = _SLUG_RE.sub("-", (text or "").lower()).strip("-")
    if len(slug) > max_length:
        slug = slug[:max_length].rstrip("-")
    return slug or "untitled"

types_compatible

types_compatible(source, target)

Determines whether a value produced as source can be passed into target.

Parameters:

Name Type Description Default
source str

Source port data type.

required
target str

Target port data type.

required

Returns:

Type Description
bool

True if the types are compatible; False otherwise.

Source code in python/src/science_adk/models.py
def types_compatible(source: str, target: str) -> bool:
    """Determines whether a value produced as source can be passed into target.

    Args:
      source: Source port data type.
      target: Target port data type.

    Returns:
      True if the types are compatible; False otherwise.
    """
    if source == target or "any" in (source, target):
        return True
    return (source, target) == ("int", "float")