Query, filter, and mutate Ontology objects using the Foundry Platform SDK and OSDK. Covers listing objects with property filters, following links between object types, applying actions, and aggregating object data. This is the primary workflow for Ontology-driven applications.
palantir-install-auth setuppalantir-core-workflow-a (data pipelines feed the Ontology)import os, foundry
client = foundry.FoundryClient(
auth=foundry.UserTokenAuth(
hostname=os.environ["FOUNDRY_HOSTNAME"],
token=os.environ["FOUNDRY_TOKEN"],
),
hostname=os.environ["FOUNDRY_HOSTNAME"],
)
ONTOLOGY = "my-company"
# List employees in Engineering, sorted by hire date
result = client.ontologies.OntologyObject.list(
ontology=ONTOLOGY,
object_type="Employee",
page_size=20,
order_by="hireDate:asc",
properties={"department": "Engineering"},
)
for obj in result.data:
p = obj.properties
print(f"{p['fullName']} | {p['department']} | hired {p['hireDate']}")
# Search with complex filters using the search endpoint
search_result = client.ontologies.OntologyObject.search(
ontology=ONTOLOGY,
object_type="Employee",
where={
"type": "and",
"value": [
{"type": "eq", "field": "department", "value": "Engineering"},
{"type": "gte", "field": "salary", "value": 100000},
],
},
page_size=50,
)
print(f"Found {len(search_result.data)} matching employees")
# Get all projects linked to an employee
employee_rid = "ri.ontology.main.object.employee-001"
linked_projects = client.ontologies.OntologyObject.list_linked_objects(
ontology=ONTOLOGY,
object_type="Employee",
primary_key="EMP-001",
link_type="assignedProjects",
)
for project in linked_projects.data:
print(f" Project: {project.properties['name']} — {project.properties['status']}")
# Promote an employee — triggers validation rules defined in Ontology
result = client.ontologies.Action.apply(
ontology=ONTOLOGY,
action_type="promoteEmployee",
parameters={
"employeeId": "EMP-001",
"newTitle": "Senior Engineer",
"newSalary": 150000,
"effectiveDate": "2026-04-01",
},
)
print(f"Validation: {result.validation}") # VALID or INVALID with reasons
# Aggregate salary by department
aggregation = client.ontologies.OntologyObject.aggregate(
ontology=ONTOLOGY,
object_type="Employee",
aggregation=[
{"type": "avg", "name": "avgSalary", "field": "salary"},
{"type": "count", "name": "headcount"},
],
group_by=[{"field": "department", "type": "exact"}],
)
for bucket in aggregation.data:
grp = bucket.group
vals = bucket.metrics
print(f"{grp['department']}: {vals['headcount']} people, avg ${vals['avgSalary']:,.0f}")
import { createClient } from "@osdk/client";
import { Employee } from "@my-app/sdk"; // generated types
// Type-safe queries with auto-completion
const engineers = await client(Employee)
.where({ department: { $eq: "Engineering" } })
.orderBy(e => e.hireDate.asc())
.fetchPage({ pageSize: 20 });
for (const emp of engineers.data) {
console.log(`${emp.fullName} — ${emp.title}`);
}
// Apply action with type-safe parameters
await client(Employee).applyAction("promoteEmployee", {
employeeId: "EMP-001",
newTitle: "Senior Engineer",
});
| Error | Cause | Solution |
|---|---|---|
ObjectTypeNotFound |
Wrong api_name | Check Ontology Manager for exact type names |
PropertyNotFound |
Wrong property name | Properties are camelCase in API, may differ from UI |
ActionValidationFailed |
Business rule violation | Read result.validation.messages for details |
LinkTypeNotFound |
Invalid link type name | Verify link type in Ontology Manager |
PermissionDenied |
Missing Ontology scope | Add api:ontology-read scope to your app |
employee_ids = ["EMP-001", "EMP-002", "EMP-003"]
for eid in employee_ids:
result = client.ontologies.Action.apply(
ontology=ONTOLOGY,
action_type="markReviewed",
parameters={"employeeId": eid, "reviewDate": "2026-03-22"},
)
status = "OK" if result.validation == "VALID" else "FAILED"
print(f" {eid}: {status}")
palantir-common-errors
palantir-performance-tuning
palantir-enterprise-rbac