SODEA

Building with Morpheus

Learn how to create, run, and evolve semantic object-based systems using the Morpheus runtime engine. This guide walks you through designing reactive logic, defining hooks, and triggering behaviors—building intelligent, self-managed software using semantic data.


1. Understanding Execution in Morpheus

Morpheus is designed to execute behavior stored inside data objects. These behaviors are defined as hooks, which are small functions that run in response to events or timers.

Each semantic object may include:

  • onTick — executed on a schedule
  • onEvent — executed when an event is received
  • onCreate, onDelete — optionally for lifecycle events

Morpheus processes these hooks in a secure runtime and can trigger other objects by emitting events.


2. Creating a Semantic Object

Here’s an example of a simple counter object that responds to time and events:

{
  "@context": "https://schema.sodea.org/core#",
  "@id": "urn:demo:counter",
  "@type": "CounterObject",
  "counter": 0,
  "status": "idle",
  "_private": {
    "hooks": {
      "onTick": {
        "language": "python",
        "code": "def run(obj, params, save, load, delete):\n    obj['counter'] += 1\n    save(obj)\n    return obj"
      }
    },
    "schedule": {
      "interval": "5s"
    }
  }
}

Save this object via the Morpheus API, and it will begin incrementing its counter every 5 seconds.


3. Writing Hooks

Hooks are stored as executable code inside your object. Morpheus currently supports:

  • Python for dynamic backend logic
  • JavaScript (optional configuration)

A hook must define a run(obj, params, save, load, delete) function and can:

  • Read/modify the object (obj)
  • Save changes
  • Trigger events by returning a trigger_event

Example of triggering an event:

if obj['counter'] > 100:
    return { "trigger_event": { "eventType": "threshold", "payload": { "value": obj['counter'] } } }

4. Event-Based Execution

You can subscribe to event types via the _private.subscriptions field. When an event is published, Morpheus will call your object’s onEvent hook if the event type matches.

"subscriptions": ["threshold", "reset"]

And the hook:

def run(obj, params, save, load, delete):
    if params.get("eventType") == "reset":
        obj["counter"] = 0
        save(obj)
    return obj

5. Monitoring Execution

All hook executions can log output to the console, visible in your admin dashboard or frontend interface (like Fountain).

Use print("something happened") to trace logic during development.


6. Advanced Patterns

  • Graph-based chaining: One object can trigger another by sending events.
  • Stateful interactions: Objects can persist state, making them long-lived agents.
  • Data-driven control: Behavior adapts based on fields in the object itself.

Example: A counter that slows down over time by adjusting its own interval.


7. Running Morpheus

Morpheus can run in multiple environments:

  • As a local dev server (default)
  • As a Flask/FastAPI app (custom deployment)
  • With different storage layers: flat file, MongoDB, etc.

It is open-source and easily extended.


8. Integrating with Fountain

Fountain is the recommended frontend for viewing, editing, and testing semantic objects.

Use Fountain to:

  • Visually browse the semantic object graph
  • Inspect logs
  • Trigger hooks
  • Create new templates

9. What’s Next?

Now that you can build reactive systems with Morpheus:


---