Developer guide
Build against objects, relationships, and capabilities. Keep vendor-specific behavior in integrations.
On this page
An intended API and SDK boundary
The intended application programming interface (API) exposes the operational model. A software development kit (SDK) would help applications use that interface. Studio, the existing Valanor application, and other consumers should operate through the same service boundary, each within its own permissions.
Existing application APIs are implementation evidence for that application. They should not be treated as a stable public ontology interface or as proof that the standalone boundary has been delivered.
Query objects and relationships
Start with an object identity and traverse defined relationships. An application reviewing Gate B would retrieve the gate, its place in North Yard, and the camera observing it. It should not need Camera 12’s vendor API or source credentials.
within the application's permitted site scope:
gate = find Asset by its mapped identity "gate-b"
place = read gate's LOCATED_AT relationship
cameras = read gate's OBSERVED_BY relationships
incidents = find Incident objects that AFFECT gate
show permitted properties, sources, and freshness
keep unknown or inaccessible context distinctA capability query should return enough context to assess suitability. Requesting an observation at East Entrance must consider coverage, operating constraints, current availability, and permission, not just whether OBSERVE appears in a list.
Read events and historical state
An application should be able to request relevant events over a time window and ask what state was known at a particular time. Specify the object or place and distinguish observation time from ingestion time.
context = Gate B within North Yard
window = the hour before the reported incident
read permitted events involving context during window
read recorded state of context at the incident time
include source times, receipt times, and evidence references
show any gaps or uncertainty in the recordHistory may be incomplete because a source was unavailable or an observation arrived late. Do not interpolate missing history into facts. A model prediction should remain separately identified by forecast time, provenance, and uncertainty.
Subscribe to permitted changes
A live application would subscribe to relevant changes after reading an initial view. Both the initial query and the update stream must respect permissions. Losing access should also stop disclosure through the stream.
open the permitted Gate B view
request updates relevant to that view
when information changes:
show the updated context and its freshness
when updates are unavailable:
show that the view may be stale
refresh through the authorized application interfaceRequest actions and inspect outcomes
A request expresses intent. It does not bypass authorization or execute a vendor command directly. The Runtime should check the actor, target, parameters, required approvals, capability constraints, and current conditions before routing accepted work.
request an inspection of Gate B for the linked Task
include the actor, purpose, and required operating constraints
if permission or capability checks reject the request:
show the reason; do not dispatch
otherwise:
retain the action execution reference
read updates and inspect the recorded outcome
require suitable evidence before marking the Task complete| Meaning | What it does not prove |
|---|---|
| Request accepted for processing | That the integration has received a command. |
| Command acknowledged by an integration | That a robot moved or a gate physically closed. |
| Execution reported complete | That every task completion criterion has been verified. |
| Outcome supported by evidence | That the same result will hold indefinitely or for another action. |
| Failed, timed out, or unknown | That repeating the request is safe. |
This table describes distinctions, not final API enum names. Request tracking, retry behavior, and approval requirements must be established in the eventual public contract. Never infer permission or successful completion solely from a response arriving.
Treat evidence access separately
An ontology query can return a reference to an image or video without returning the file itself. Applications must use the authorized evidence-access path and handle unavailable or expired evidence. Reading a related object does not grant unrestricted media access.
Do not move device credentials into a browser or embed vendor logic in application code. Integration authorization belongs at the appropriate service or connector boundary. The public authentication and credential-management procedure remains to be specified.
What to establish before building an integration
- The concrete objects, relationships, and source mappings needed by the application.
- The applicable permissions and how they apply to queries, relationships, subscriptions, actions, and evidence.
- A versioned interface contract covering pagination, filtering, errors, compatibility, and change delivery.
- Action safety, approval requirements, outcome evidence, and retry behavior for the actual integration.
- Which capabilities are implemented in the target environment and which still require design or validation.
- Connecting existing systems
Evaluate source access, mappings, and real compatibility limits.
- Discuss your integration
Bring the interface, version, deployment constraints, and operations you need to evaluate.
How to read these examples
Each operation runs within the requesting actor’s permitted scope. Establish the actual access contract for your environment before implementation. Device credentials belong at the integration boundary, not inside an application query.
The examples use fictional identifiers for North Yard, Gate B, and an inspection task. Object references identify records; knowing an identifier does not grant permission to read or act on it.
getObjects() and getObject()
Use a collection query when the user is exploring a site. Use a single-object lookup once the application has an authorized object reference. Return only the properties needed for the view.
| Input | Meaning |
|---|---|
| Site scope | Limits the query to the site or sites the actor is allowed to access. |
| Type and property filters | Selects objects matching the question, such as Assets at East Entrance. |
| Requested properties | Keeps the view focused on relevant, permitted information. |
| Page boundary | Allows a bounded result set. Final pagination semantics are not specified here. |
assets = ontology.getObjects({
site: "north-yard",
type: "Asset",
filter: { name: "Gate B" },
properties: ["name", "operatingStatus"]
})
// Names may be ambiguous. Let the user select the correct object.
gate = ontology.getObject({ object: selectedAssetReference })
show(gate.permittedProperties, gate.freshness)An empty result means no visible matches for that query. It does not prove that the site contains no such equipment. A denied or unavailable record must not be converted into a fabricated object with default values.
getRelationships()
Relationships supply context around an object. Ask for the intended relationship direction and type rather than assuming that any nearby object is related.
location = ontology.getRelationships({
object: gate.reference,
relationship: "LOCATED_AT",
direction: "outgoing"
})
observers = ontology.getRelationships({
object: gate.reference,
relationship: "OBSERVED_BY",
direction: "outgoing"
})
showPermittedContext(location, observers)Each connected object and relationship remains subject to permissions. A permitted gate record does not automatically expose every person, incident, or evidence file associated with it.
getObservations() and getEvents()
Observations describe what a source reported or inferred. Events describe reported occurrences. Read them together when investigating, while preserving their different meanings.
observations = ontology.getObservations({
object: gate.reference,
from: reviewWindow.start,
to: reviewWindow.end
})
events = ontology.getEvents({
location: eastEntrance.reference,
from: reviewWindow.start,
to: reviewWindow.end
})
for record in observations + events:
show(record.source, record.observedAt, record.receivedAt)
show(record.confidenceIfApplicable, record.evidenceReferences)Define the time window and time basis before comparing results. An observation that arrived late may describe an earlier event. Confidence, when provided, is not a substitute for reviewing evidence and context.
getCurrentState() and getStateAt()
Current state answers what is known now. Historical state answers what is recorded for a selected point in time. Neither should hide gaps in the source record.
current = ontology.getCurrentState({ object: gate.reference })
earlier = ontology.getStateAt({
object: gate.reference,
at: incident.occurredAt
})
compare(current, earlier)
showFreshnessAndUnknownValues(current, earlier)| Result | Application behavior |
|---|---|
| Recent supported value | Show the value with its source time. |
| Stale value | Display the last known value as stale, not as a live reading. |
| No recorded state for that time | Explain the gap instead of interpolating a fact. |
| Corrected source report | Preserve the distinction between the earlier report and later correction. |
getPredictedState()
A forecast needs a subject, a target time or horizon, and enough provenance to distinguish it from an observation. Applications should expose uncertainty and avoid treating a forecast as a confirmed future event.
forecast = ontology.getPredictedState({
object: gate.reference,
horizon: selectedForecastWindow
})
if forecast is available:
showAsPrediction(forecast.value, forecast.targetTime)
show(forecast.uncertainty, forecast.provenance)
else:
show("No supported forecast is available for this view")getCapabilities() and executeAction()
Capabilities help an application discover which operations are suitable. An execution request still needs its own permission and operating checks. The word execute in a conceptual function name does not mean completion is synchronous or guaranteed.
capabilities = ontology.getCapabilities({ object: agent.reference })
if supportsRequiredInspection(capabilities, task.constraints):
request = ontology.executeAction({
target: agent.reference,
action: "Inspect",
context: { task: task.reference, place: eastEntrance.reference }
})
showRequestForReview(request.reference)
else:
show("No suitable inspection capability is currently available")An application-side suitability check helps the user, but is not authorization. The service must evaluate the request again using the actor’s permissions, required approvals, availability, and current conditions.
| What to inspect | Why |
|---|---|
| Acceptance or rejection | Distinguishes a valid request from work that was never authorized. |
| Acknowledgment | Shows that the integration received a command, not that the physical outcome occurred. |
| Execution result | Reports progress, completion, failure, or an unknown outcome. |
| Supporting observation or evidence | Supports a decision about whether the Task’s completion criteria were met. |
Subscriptions, limits, and errors
A live-update subscription would deliver permitted changes relevant to a view. No stable subscription function name or transport is specified here. See the developer model for the intended read, update, and recovery behavior.
| Condition | Useful response |
|---|---|
| Access denied | Explain that the operation is unavailable for this actor without leaking protected details. |
| No visible match | Offer a revised query, not a guessed identity. |
| Source stale or unavailable | Preserve the last known context and clearly mark its limits. |
| Rate limited or temporarily unavailable | Follow the published retry contract once available; do not blindly repeat physical commands. |
| Capability unsuitable | Show the constraint preventing the requested operation. |
| Outcome unknown | Keep the uncertainty visible and route the work for review. |
- Developer model
Read the service boundary and intended live-update behavior.
- Workflow examples
Combine these operations into useful site workflows.