Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

The notebook: the catalog as a graph

Four cells, one story: the catalog is a list, then a card, then a graph, then a query. examples/python/catalog.ipynb is the notebook; examples/python/catalog.py is the same cells as a script, which is what was run to produce the output below (against a served ikigai-cli 0.1.18 — the counts are that host’s, and yours will differ).

pip install rdflib /path/to/ikigai-python
ikigai serve /tmp/ikbook-kernel.sock &
python3 examples/python/catalog.py /tmp/ikbook-kernel.sock

1. The catalog as a list

    # 1. The catalog as a list: every name the kernel binds, with the endpoint behind it
    #    and — for a mounted peer — where it is served from.
    entries = k.entries()
    print(len(entries), "bound names; the first three:")
    for entry in entries[:3]:
        print(" ", entry.pattern, "→", entry.endpoint)
261 bound names; the first three:
  urn:agent:select → agent-select
  urn:client:issue → client-issue
  urn:cms:bookmarks → bookmarks

entries() is what list prints at the shell, as data: pattern, endpoint id, and — for a mounted peer — where it is served from. A client discovers what it can reach instead of being told.

2. One card, as data

    # 2. One endpoint's card, as data — the JSON Meta face, parsed.
    card = k.describe("urn:iki:fn:toUpper")
    print(card["title"], "—", card["summary"])
    for arg in card["inputs"]:
        print("  input", arg["name"], "required" if arg.get("required", True) else "optional")
Upper-case — Upper-cases the UTF-8 text supplied in the `in` argument.
  input in required

describe is the JSON face of Meta, parsed. This is the dictionary an agent’s tool definition is projected from — Why an endpoint describes itself, reached by dict lookup.

3. The whole catalog, as a graph

    # 3. The whole catalog as a graph. `urn:kernel:catalog` answers as Turtle, and rdflib
    #    parses it; from here on it is RDF and the vocabulary is the schema.
    turtle = k.source("urn:kernel:catalog").text
    g = rdflib.Graph()
    g.parse(data=turtle, format="turtle")
    print(len(g), "triples in the catalog")
3289 triples in the catalog

urn:kernel:catalog answers as Turtle, rdflib parses it, and from here on it is RDF: the vocabulary at https://ikigai-rs.dev/ns# is the schema, every endpoint and every input is a node with a stable IRI, and a graph library’s whole toolkit applies.

4. One query

    # 4. One SPARQL query over it: which endpoints take a string? The same question the
    #    graph-face chapter asked with `urn:sparql:select`, asked here by a client.
    query = """
        PREFIX ik: <https://ikigai-rs.dev/ns#>
        SELECT DISTINCT ?id WHERE {
          ?endpoint a ik:Endpoint ; ik:id ?id ; (ik:input | ik:action/ik:input) ?input .
          ?input ik:class <http://www.w3.org/2001/XMLSchema#string> .
        } ORDER BY ?id
    """
    for row in g.query(query):
        print(" ", row.id)
  decrypt
  encrypt
  eval
  rdf-from-sexpr
  sexpr-from-rdf
  sexpr-to-rdf
  sign
  sparql-from-sexpr
  tz-convert
  tz-now
  verify

The same question The graph face asked with urn:sparql:select — which endpoints take a string? — asked here by a client with its own query engine, over a catalog it fetched by name. Two things to notice in the answer. toUpper is not in it, because ikigai-fn 0.2.0 declares no class on its in input; an undeclared class is invisible to the question, which is the argument for declaring one. And the property path (ik:input | ik:action/ik:input) is the one the graph-face chapter needed too: a multi-verb endpoint’s inputs hang off its action nodes.

⚠ The catalog you get is the catalog of the host you connected to. The CLI’s is a few hundred endpoints from a dozen crates; the tutorial host’s is eleven. Both are the same shape, and a query written against one runs against the other — but the answer is a fact about a host, not about ikigai.