Palantir's Actions and Rules: Bridging Data Insight to Business Operations
Everyone who has used a BI tool has experienced this scenario:
Palantir's Actions and Rules: Bridging Data Insight to Business Operations
“Series: S1 Palantir Decoded · Article 11 | Level: Beginner | Reading Time: 15 min
#TL;DR
- Palantir Actions are the core mechanism for turning data insights into business operations -- each Action is an atomic, auditable, permission-controlled business operation unit with parameter validation, preconditions, side-effect declarations, and permission constraints.
- The Rules engine implements automated decision-making through a "condition -> trigger -> action chain" pattern, enabling systems to not just "see problems" but "automatically handle them" -- this is the fundamental difference between Palantir and every BI platform.
- coomia-dip implements this complete closed loop through ActionEngine (10 executor types) and ReasoningEngine (rules engine), with FunctionRuntime supporting Python/TypeScript/Groovy/WASM/Kotlin sandboxed execution.
#Introduction: The Ultimate BI Dilemma -- "I Can See It, Now What?"
Everyone who has used a BI tool has experienced this scenario:
Traditional BI platform workflow:
Step 1: See the report
+--------------------------------------+
| Inventory Alert Dashboard |
| |
| Material A-2047: Stock 12 (below safety stock of 50)
| Material B-1193: Stock 0 (out of stock!)
| Material C-0872: Stock 8 (below safety stock of 30)
| |
| [Export to Excel] |
+--------------------------------------+
Step 2: Open email client, write email to procurement
Step 3: Procurement reads email, opens ERP system
Step 4: Look up supplier information in ERP
Step 5: Create purchase order
Step 6: Wait for approval
Step 7: Approval granted, send to supplier
Step 8: Track delivery status...
The entire process involves 4 systems, 3 people, at least 2 days.
Meanwhile, the stockout costs $7,000 per day.
The root cause: Traditional BI only solves "seeing," not "doing."
Palantir's Actions and Rules exist precisely to bridge this gap.
Palantir's closed-loop workflow:
+--------------------------------------+
| Inventory Alert Dashboard |
| |
| Material A-2047: Stock 12 |
| [Restock] [Switch Supplier] [Pause Line]
| |
| > Rules auto-triggered: |
| - Restock request sent to |
| preferred supplier |
| - Warehouse manager notified |
| - Production schedule priority |
| adjusted |
+--------------------------------------+
Same scenario: 0 extra systems, 0 emails, 30 seconds.
This is the "data-to-action closed loop" -- one of Palantir's core competitive advantages.
#Part 1: Anatomy of an Action
#1.1 What Is an Action?
In Palantir Foundry, an Action is a structured business operation unit. It is not a simple API call, but a complete semantic description of an operation:
Complete Action structure:
+-----------------------------------------------+
| ActionType: "Restock Order" |
| |
| +-------------------------------------------+ |
| | Parameters | |
| | - materialId: ObjectReference<Material> | |
| | - quantity: Integer (min: 1, max: 10000) | |
| | - supplierId: ObjectReference<Supplier> | |
| | - urgency: Enum(NORMAL, URGENT, CRITICAL) | |
| | - notes: String (optional) | |
| +-------------------------------------------+ |
| |
| +-------------------------------------------+ |
| | Preconditions | |
| | - material.status != DISCONTINUED | |
| | - supplier.status == ACTIVE | |
| | - user.role IN [BUYER, MANAGER] | |
| | - quantity <= material.maxOrderQuantity | |
| +-------------------------------------------+ |
| |
| +-------------------------------------------+ |
| | Side Effects (declared) | |
| | - CREATE PurchaseOrder | |
| | - UPDATE Material.lastOrderDate | |
| | - CREATE Notification -> warehouse_mgr | |
| +-------------------------------------------+ |
| |
| +-------------------------------------------+ |
| | Permissions | |
| | - REQUIRES: procurement:order:create | |
| | - REQUIRES: material:read | |
| | - IF urgency == CRITICAL: | |
| | REQUIRES: procurement:emergency | |
| +-------------------------------------------+ |
| |
| +-------------------------------------------+ |
| | Validation Rules | |
| | - totalCost <= user.approvalLimit | |
| | - supplier NOT IN blacklist | |
| | - delivery_date within fiscal_year | |
| +-------------------------------------------+ |
+-----------------------------------------------+
#1.2 The Six Components of an ActionType
| Component | Purpose | Example |
|---|---|---|
| Parameters | Define required inputs | Material ID, quantity, supplier |
| Preconditions | Conditions that must be met before execution | Material not discontinued, supplier active |
| Side Effects | Declare what the operation will change | Create order, update inventory |
| Permissions | Required permission set | Buyer or manager role |
| Validation | Business rule checks | Amount within approval limit |
| Audit Config | Audit configuration | Record operator, timestamp, change details |
#1.3 Why "Side Effect Declarations" Matter So Much
In traditional systems, knowing what an API call does requires reading the code. Palantir Actions explicitly declare all side effects:
Traditional API: Palantir Action:
POST /api/restock ActionType: Restock
Body: {materialId, qty} Side Effects:
- CREATE PurchaseOrder
Returns: {success: true} - UPDATE Material.lastOrderDate
- UPDATE Material.pendingQty
// What did it actually do? - CREATE AuditLog
// Who knows... - SEND Notification -> buyer
// Read 500 lines of code
// Everything is visible at a glance
This enables:
- Permission systems to know exactly which objects and permissions to check
- Audit systems to precisely record every change
- Rollback mechanisms to know which operations to reverse
- Impact analysis to show users what will happen before execution
#Part 2: Action Execution Lifecycle
#2.1 From Button Click to Operation Complete
User clicks [Restock]
|
v
+--------------+
| 1. Parameter | <-- Form popup: enter quantity, select supplier
| Collection| <-- Real-time validation: quantity range, supplier status
| & Validate|
+------+-------+
|
v
+--------------+
| 2. Precondi- | <-- Check if material is orderable
| tion Check| <-- Check if supplier is active
+------+-------+
| Conditions met
v
+--------------+
| 3. Permission| <-- Does user have ordering permission?
| Check | <-- Is amount within approval limit?
+------+-------+
| Permission granted
v
+--------------+
| 4. Impact | <-- "This will create 1 purchase order,
| Preview | estimated amount $1,800"
| (Dry Run) |
+------+-------+
| User confirms
v
+--------------+
| 5. Transact- | <-- Execute all side effects in one transaction
| ional Exec| <-- Atomic: all succeed or all rollback
+------+-------+
|
v
+--------------+
| 6. Audit | <-- Record operator, timestamp, parameters, result
| Logging | <-- Record before/after state snapshots
+------+-------+
|
v
+--------------+
| 7. Post-exec | <-- Trigger associated Rules
| Triggers | <-- Send notifications
+--------------+
#2.2 The Dry Run Mechanism
Palantir's Dry Run is an extraordinarily powerful feature -- previewing the full impact of an operation without actually executing it:
# Dry Run preview response
{
"action": "Restock",
"preview": {
"objects_created": [
{"type": "PurchaseOrder", "properties": {
"supplier": "ABC Electronics",
"total_amount": 12500,
"expected_delivery": "2026-04-10"
}}
],
"objects_modified": [
{"type": "Material", "id": "A-2047", "changes": {
"pending_quantity": {"before": 0, "after": 100},
"last_order_date": {"before": "2026-02-15", "after": "2026-03-24"}
}}
],
"notifications": [
{"to": "warehouse_mgr", "template": "new_order_placed"}
],
"estimated_cost": 12500,
"requires_approval": False
}
}
Users can see every change that will occur before confirming -- something nearly impossible in traditional systems.
#Part 3: The Rules Engine -- Automated Decision Making
#3.1 From "Humans Find Problems" to "Systems Handle Problems"
Rules are Palantir's automated decision engine. The core pattern is:
Condition -----> Trigger -----> Action Chain
Example:
+---------------------------+
| Rule: Auto-Restock |
+---------------------------+
| |
| WHEN: |
| material.stock_level |
| < material.safety_stock |
| AND material.status |
| == ACTIVE |
| |
| THEN: |
| 1. Calculate restock qty |
| (EOQ formula) |
| 2. Select optimal supplier|
| (price+lead time+score)|
| 3. Create purchase order |
| 4. Notify warehouse mgr |
| 5. Update demand forecast |
| |
| UNLESS: |
| Open restock order exists |
| OR material being phased |
| out |
| |
| THROTTLE: |
| Same material: max 1 |
| trigger per 24 hours |
+---------------------------+
#3.2 Three Rule Triggering Modes
| Mode | When Triggered | Use Case | Example |
|---|---|---|---|
| Event-driven | On object state change | Real-time response | Restock when inventory drops below threshold |
| Scheduled | By Cron expression | Periodic checks | Daily check for expiring contracts |
| Manual | User-initiated | Batch processing | Quarterly supplier review |
#3.3 Rule Chains -- Orchestrating Complex Scenarios
Real business scenarios rarely involve a single rule. Palantir supports Rule Chains:
Rule Chain Example: Equipment Anomaly Handling
Event: Sensor temperature > threshold
|
v
+----------------------+
| Rule 1: Initial |
| Assessment |
| IF temp > 80C |
| AND duration > 5min |
| THEN: Create alert |
| severity = WARN |
+----------+-----------+
| Alert created event
v
+----------------------+
| Rule 2: Escalation |
| IF temp > 95C |
| OR same device has |
| 3 alerts in 24h |
| THEN: Escalate to |
| CRITICAL |
| Notify shift mgr |
+----------+-----------+
| Escalation event
v
+----------------------+
| Rule 3: Auto-Response|
| IF severity == |
| CRITICAL |
| AND device supports |
| remote control |
| THEN: Reduce power |
| to 50% |
| Create repair order|
| Notify maintenance |
+----------+-----------+
| Repair order created
v
+----------------------+
| Rule 4: Line Adjust |
| IF critical device |
| goes offline |
| THEN: Reschedule |
| production |
| Notify downstream |
| Update delivery |
| forecast |
+----------------------+
These four rules are defined independently but automatically chained through events. This is the power of a rule engine -- each rule stays simple, but composed together they handle extremely complex scenarios.
#Part 4: Functions -- User-Defined Logic
#4.1 Where Functions Fit
When built-in Actions and Rules are not enough, users can write custom Functions:
Complexity spectrum:
Simple <-------------------------------------> Complex
[Built-in Action] [Rules] [Functions] [Pipeline]
Click button Auto- Custom Data
to execute trigger logic pipeline
Coding Design
required required
#4.2 Writing Functions
Palantir supports Functions in TypeScript and Python:
// TypeScript Function: Select optimal supplier
import { Function, OntologyObject } from "@palantir/functions-api";
@Function()
export function selectOptimalSupplier(
material: OntologyObject<"Material">,
requiredQuantity: number
): OntologyObject<"Supplier"> {
// Get all active suppliers for this material
const suppliers = material.suppliers
.filter(s => s.status === "ACTIVE")
.filter(s => s.available_capacity >= requiredQuantity);
if (suppliers.length === 0) {
throw new UserFacingError(
"No available supplier can fulfill this order quantity"
);
}
// Sort by composite score: price 40% + lead time 30% + quality 30%
return suppliers.sort((a, b) => {
const scoreA = a.unit_price * 0.4
+ a.avg_delivery_days * 0.3
+ (5 - a.quality_rating) * 0.3;
const scoreB = b.unit_price * 0.4
+ b.avg_delivery_days * 0.3
+ (5 - b.quality_rating) * 0.3;
return scoreA - scoreB;
})[0];
}
# Python Function: Anomaly detection
from palantir.functions import function
from palantir.ontology import ObjectSet
@function()
def detect_anomalies(
equipment_id: str,
lookback_hours: int = 24
) -> list[dict]:
"""Detect anomaly patterns in equipment sensor data."""
readings = Objects.search("SensorReading") \
.filter(equipment_id=equipment_id) \
.filter(timestamp__gte=now() - hours(lookback_hours)) \
.order_by("timestamp") \
.all()
anomalies = []
window_size = 10
for i in range(window_size, len(readings)):
window = readings[i - window_size:i]
mean = sum(r.value for r in window) / window_size
std = (sum((r.value - mean) ** 2
for r in window) / window_size) ** 0.5
if abs(readings[i].value - mean) > 3 * std:
anomalies.append({
"timestamp": readings[i].timestamp,
"value": readings[i].value,
"expected_range": [mean - 3*std, mean + 3*std],
"severity": "HIGH"
if abs(readings[i].value - mean) > 5 * std
else "MEDIUM"
})
return anomalies
#4.3 The Function Security Sandbox
Functions do not run on the user's machine -- they execute in Palantir's secure sandbox:
Function Execution Environment:
+----------------------------------------------+
| Palantir Function Runtime |
| |
| +------------------------------------------+ |
| | Security Sandbox | |
| | +--------------------------------------+ | |
| | | User Function Code | | |
| | | - Can only access declared Ontology | | |
| | | objects | | |
| | | - No direct network/filesystem | | |
| | | access | | |
| | | - Execution time limit (default 30s)| | |
| | | - Memory limit (default 256MB) | | |
| | +--------------------------------------+ | |
| | | |
| | +--------------------------------------+ | |
| | | Ontology API (restricted interface) | | |
| | | - Objects.search() | | |
| | | - Objects.get() | | |
| | | - Actions.apply() | | |
| | +--------------------------------------+ | |
| +------------------------------------------+ |
| |
| Permissions inherited from caller |
| <-- Critical security design |
+----------------------------------------------+
#Part 5: Webhook Integration and Batch Operations
#5.1 Webhooks -- Connecting the Outside World
Actions can not only manipulate objects within the Ontology but also connect to external systems through Webhooks:
Webhook Action Flow:
+----------+ +--------------+ +--------------+
| Palantir | | Webhook | | External |
| Action |---->| Gateway |---->| System |
| | | - Signature | | (ERP/CRM/ |
| | | verify | | MES/...) |
| | | - Retry | | |
| | | - Timeout | | |
+----------+ +------+-------+ +------+-------+
| |
| Callback confirm |
|<--------------------+
|
v
+--------------+
| Update status|
| Write audit |
+--------------+
Webhook configuration example:
{
"actionType": "sync_order_to_erp",
"webhook": {
"url": "https://erp.company.com/api/v2/purchase-orders",
"method": "POST",
"headers": {
"Authorization": "Bearer ${secrets.erp_token}",
"Content-Type": "application/json"
},
"body_template": {
"order_id": "${action.params.orderId}",
"material_code": "${object.Material.code}",
"quantity": "${action.params.quantity}",
"supplier_code": "${object.Supplier.erp_code}"
},
"retry": {
"max_attempts": 3,
"backoff": "exponential",
"initial_delay_ms": 1000
},
"timeout_ms": 30000,
"success_condition": "response.status == 201"
}
}
#5.2 Batch Actions
When dealing with large-scale data, executing Actions one by one is too slow. Palantir supports batch operations:
Batch Action Execution:
Input: 2,847 orders needing status updates
+------------------------------------------+
| Batch Action: Bulk Update Order Status |
| |
| Batch Strategy: 100 per batch |
| |
| Batch 1: [###########] 100/100 Done |
| Batch 2: [###########] 100/100 Done |
| Batch 3: [###########] 100/100 Done |
| ... |
| Batch 28: [###########] 100/100 Done |
| Batch 29: [####### ] 47/100 Done |
| |
| Result: 2,841 succeeded / 6 failed |
| Failure reasons: |
| - 3: Order modified by another user |
| - 2: Supplier deactivated |
| - 1: Insufficient permissions |
| |
| [Retry Failed] [Export Report] [Details] |
+------------------------------------------+
Key design principles for batch operations:
| Principle | Description |
|---|---|
| Partial failure tolerance | Single record failure does not affect others |
| Progress visibility | Real-time progress display |
| Selective retry | Only retry failed records |
| Complete audit | Each record audited independently |
| Concurrency control | Optimistic locking prevents conflicts |
#Part 6: The Action Audit Trail
#6.1 Why Audit Matters
In regulated industries like finance, healthcare, and government, "who did what when" is not optional -- it is a legal requirement.
Action Audit Record Structure:
+----------------------------------------------------+
| Audit Entry |
| |
| Action ID: act_20260324_143052_a7b3c |
| Action Type: UpdateOrderStatus |
| Timestamp: 2026-03-24T14:30:52.847Z |
| User: zhang.wei@company.com |
| User Role: procurement_manager |
| IP Address: 10.0.12.47 |
| Session: sess_x8k2m |
| |
| Parameters: |
| orderId: PO-2026-00847 |
| newStatus: APPROVED |
| comment: "Price confirmed, purchase approved" |
| |
| Affected Objects: |
| PurchaseOrder/PO-2026-00847: |
| status: PENDING -> APPROVED |
| approved_by: null -> zhang.wei |
| approved_at: null -> 2026-03-24T14:30:52Z |
| |
| Triggered Rules: |
| - rule_auto_notify_supplier (SUCCESS) |
| - rule_update_budget_consumed (SUCCESS) |
| |
| Execution Time: 127ms |
| Result: SUCCESS |
+----------------------------------------------------+
#6.2 Immutability of Audit Logs
Audit Log Storage Architecture:
Action Execution
|
v
+------------+ +------------+ +------------+
| Synchronous| | Async | | Compliance |
| Write to |--->| Archive to |--->| Periodic |
| Append-Only| | Object | | Audit |
| Database | | Storage | | Report |
+------------+ | (Immutable)| | Generation |
| +------------+ +------------+
|
| Integrity guarantee
v
+------------+
| Hash chain |
| Each record|
| hash incl. |
| previous |
| record hash|
+------------+
#Part 7: How coomia-dip Implements Actions and Rules
#7.1 ActionEngine's 10 Executor Types
coomia-dip ActionEngine provides 10 executor types covering all common business operation scenarios:
coomia-dip ActionEngine Architecture:
+--------------+
| ActionEngine |
| (Dispatcher)|
+------+-------+
|
+---------------+---------------+
| | |
+-----+-----+ +-----+-----+ +-----+-----+
| Object Ops | | Relation | | Extended |
+-----+-----+ | Ops | | Ops |
| +-----+-----+ +-----+-----+
+------+------+ +---+---+ +------+----------+
| | | | | | | | |
v v v v v v v v v
Create Update Delete Create Delete Invoke Web- Noti- Simple Compo-
Object Object Object Rela. Rela. Func. hook fic. Op site
| Executor | Function | Example |
|---|---|---|
| CreateObject | Create Ontology object | Create purchase order |
| UpdateObject | Update object properties | Change order status |
| DeleteObject | Delete object (soft delete) | Cancel voided order |
| CreateRelation | Create inter-object relation | Link order to supplier |
| DeleteRelation | Remove inter-object relation | Unbind supplier |
| InvokeFunction | Call custom function | Run pricing logic |
| Webhook | Call external HTTP endpoint | Sync data to ERP |
| Notification | Send notification | Email/SMS/in-app message |
| SimpleOp | Simple expression operation | Field assignment, math |
| CompositeOp | Compose multiple operations | Orchestrate complex workflows |
#7.2 CompositeOp -- Operation Orchestration
CompositeOp is the most powerful executor type, composing multiple operations into a single transaction:
# coomia-dip CompositeOp definition example
from ontology_sdk import ActionBuilder, CompositeOp
restock_action = ActionBuilder("restock_material") \
.parameter("material_id", type="object_ref",
object_type="Material") \
.parameter("quantity", type="integer", min=1) \
.precondition("material.status == 'ACTIVE'") \
.precondition(
"material.stock_level < material.safety_stock") \
.composite_op([
CompositeOp.invoke_function(
"select_optimal_supplier",
args={"material_id": "${params.material_id}",
"quantity": "${params.quantity}"},
output_as="selected_supplier"
),
CompositeOp.create_object(
"PurchaseOrder",
properties={
"material_id": "${params.material_id}",
"supplier_id":
"${steps.selected_supplier.id}",
"quantity": "${params.quantity}",
"status": "PENDING",
"created_by": "${context.user.id}"
},
output_as="new_order"
),
CompositeOp.update_object(
"${params.material_id}",
updates={
"pending_quantity":
"${object.pending_quantity"
" + params.quantity}",
"last_order_date": "${now()}"
}
),
CompositeOp.notification(
template="new_order_created",
recipients=["warehouse_manager"],
data={"order_id": "${steps.new_order.id}"}
)
]) \
.build()
#7.3 ReasoningEngine -- Rules Engine Implementation
coomia-dip ReasoningEngine is the core of the rules engine, implementing complete condition evaluation and action triggering:
coomia-dip ReasoningEngine Architecture:
+---------------------------------------------------+
| ReasoningEngine |
| |
| +---------------+ +------------------------+ |
| | Event Bus |---->| Rule Matcher | |
| | | | Match trigger conditions| |
| | - ObjectChanged| | | |
| | - TimerFired | | Condition Evaluator: | |
| | - ActionDone | | - Property comparisons | |
| | - ExternalEvent| | - Aggregation checks | |
| +---------------+ | - Time-based conditions | |
| | - Cross-object queries | |
| +-----------+------------+ |
| | |
| v |
| +------------------------+ |
| | Action Chain Executor | |
| | Execute actions in order| |
| | | |
| | Step 1 -> Step 2 -> ... | |
| | | |
| | Supports: | |
| | - Conditional branching | |
| | - Parallel execution | |
| | - Error handling | |
| | - Retry strategies | |
| +------------------------+ |
+---------------------------------------------------+
#7.4 FunctionRuntime -- Multi-Language Sandbox
coomia-dip FunctionRuntime supports secure sandboxed execution in five languages:
FunctionRuntime Multi-Language Support:
+----------------------------------------------+
| FunctionRuntime |
| |
| +----------+ +----------+ +----------+ |
| | Python | |TypeScript| | Groovy | |
| | Sandbox | | Sandbox | | Sandbox | |
| | | | | | | |
| | CPython | | Deno | | GraalVM | |
| | 3.11+ | | Runtime | | Sandbox | |
| +----------+ +----------+ +----------+ |
| |
| +----------+ +----------+ |
| | WASM | | Kotlin | |
| | Sandbox | | Sandbox | |
| | | | | |
| | Wasmtime | | Kotlin | |
| | Runtime | | Script | |
| +----------+ +----------+ |
| |
| Common Capability Layer: |
| +------------------------------------------+ |
| | - Ontology API access (permission-gated) | |
| | - Execution time limit (default 30s) | |
| | - Memory limit (default 256MB) | |
| | - CPU limit (single core, configurable) | |
| | - Network access control (default deny) | |
| | - Filesystem isolation (read-only tmpdir) | |
| +------------------------------------------+ |
+----------------------------------------------+
Suitable scenarios for each language sandbox:
| Language | Best For | Advantage |
|---|---|---|
| Python | Data analysis, ML inference, scientific computing | Rich data science ecosystem |
| TypeScript | Frontend logic, API integration, string processing | Type safety, rich ecosystem |
| Groovy | Rule expressions, dynamic scripting | JVM ecosystem, DSL-friendly |
| WASM | High-performance computing, cross-language | Near-native performance, secure isolation |
| Kotlin | JVM integration, Android extensions | Java interoperability |
#Part 8: End-to-End Business Closed Loop in Practice
#8.1 Scenario: Intelligent Procurement Workflow
Let us use a complete example to connect Actions, Rules, and Functions:
+--------------------------------------------------------+
| Complete Closed Loop: Intelligent Procurement |
| |
| (1) Sensor data -> Inventory system updates stock qty |
| | |
| v |
| (2) Rule triggers: stock < safety stock |
| | |
| v |
| (3) Function executes: selectOptimalSupplier() |
| - Compare 3 suppliers on price, lead time, score |
| - Check annual contract remaining budget |
| - Return recommended supplier + suggested qty |
| | |
| v |
| (4) Action executes: Create PO (CompositeOp) |
| - CreateObject: PurchaseOrder |
| - CreateRelation: PO -> Supplier |
| - UpdateObject: Material.pendingQty |
| - Notification -> procurement manager |
| | |
| v |
| (5) Rule triggers: order amount > $7,000 |
| | |
| v |
| (6) Action executes: Create approval task |
| - Route to department director |
| - Set 48-hour approval SLA |
| | |
| v |
| (7) Director approves (manual Action: ApproveOrder) |
| | |
| v |
| (8) Rule triggers: order status -> APPROVED |
| - Webhook -> ERP system sync |
| - Webhook -> Supplier portal notification |
| - UpdateObject: Budget consumed amount |
| |
| Full process: 7 auto steps + 1 manual = 2 days -> 2h |
+--------------------------------------------------------+
#8.2 Implementation with coomia-dip SDK
from ontology_sdk import OntoPlatform, ActionBuilder, RuleBuilder
platform = OntoPlatform(endpoint="grpc://localhost:9090")
# Define Rule: Auto-restock when below safety stock
low_stock_rule = RuleBuilder("auto_restock") \
.description("Auto-trigger restock when inventory"
" drops below safety stock") \
.when("Material") \
.condition("object.stock_level < object.safety_stock") \
.condition("object.status == 'ACTIVE'") \
.unless("object.pending_quantity > 0") \
.throttle(hours=24, per="object.id") \
.then_action("restock_material", {
"material_id": "${trigger.object.id}",
"quantity": "${trigger.object.safety_stock"
" - trigger.object.stock_level}"
}) \
.build()
# Define Rule: Auto-route large orders for approval
approval_rule = RuleBuilder("auto_approval_routing") \
.description("Route purchase orders above threshold"
" for approval") \
.when("PurchaseOrder") \
.condition("object.status == 'PENDING'") \
.condition("object.total_amount > 50000") \
.then_action("create_approval_task", {
"order_id": "${trigger.object.id}",
"approver_role": "department_director",
"sla_hours": 48
}) \
.build()
# Register rules
platform.reasoning.register_rule(low_stock_rule)
platform.reasoning.register_rule(approval_rule)
# Execute Action (manual trigger)
result = platform.actions.execute(
action_type="restock_material",
params={
"material_id": "MAT-A2047",
"quantity": 100
},
dry_run=True # Preview first
)
print(f"Preview: Will create "
f"{len(result.preview.objects_created)} objects")
print(f"Estimated cost: ${result.preview.estimated_cost}")
# Confirm execution
result = platform.actions.execute(
action_type="restock_material",
params={
"material_id": "MAT-A2047",
"quantity": 100
},
dry_run=False # Actually execute
)
print(f"Result: {result.status}")
print(f"Audit ID: {result.audit_id}")
#Part 9: Actions vs. Traditional Approaches
#9.1 Comparison with REST APIs
| Dimension | REST API | Palantir Actions |
|---|---|---|
| Semantics | Technical ops (POST/PUT/DELETE) | Business ops (restock/approve/transfer) |
| Parameter validation | Hand-coded | Declaratively defined |
| Permissions | Middleware interception | Built into Action definition |
| Audit | Separate implementation | Automatic recording |
| Impact preview | Not supported | Built-in Dry Run |
| Batch operations | Build yourself | Framework support |
| Side effects | Implicit (read the code) | Explicitly declared |
#9.2 Comparison with Workflow Engines
Traditional Workflow Engine (Camunda/Activiti):
+----------+ +----------+ +----------+
| Workflow |---->| External |---->| Database |
| BPMN | | Services | | (SQL) |
| Diagram | | (REST) | | |
+----------+ +----------+ +----------+
Process def Business logic Data storage
(Three separate layers requiring extensive glue code)
Palantir Actions + Rules:
+------------------------------------------+
| Ontology |
| |
| Objects <--> Actions <--> Rules |
| (Data) (Operations) (Logic) |
| |
| All unified under Ontology semantics |
| (Zero glue code) |
+------------------------------------------+
#Key Takeaways
-
The core value of Actions lies in "side effect declarations" -- each Action explicitly declares which objects it will create, modify, or delete. This enables automatic permission checking, audit logging, impact preview, and rollback mechanisms without manual coding. This is the fundamental design difference between Palantir and traditional APIs.
-
The Rules engine implements the "see-to-do" automation loop -- through the "condition -> trigger -> action chain" pattern, systems can automatically execute a series of operations when business conditions are detected. Each individual rule stays simple, but through event chaining they can handle extremely complex business scenarios.
-
coomia-dip provides ActionEngine with 10 executor types, ReasoningEngine for rules, and FunctionRuntime with 5 language sandboxes -- these three components together cover everything from simple button clicks to complex automated decision chains. The CompositeOp executor allows composing multiple operations into atomic transactions, which is the key to implementing enterprise-grade business processes.
#Next Article Preview
“Article 12: Palantir's Security Model -- Why Governments Trust It with Classified Data
Actions and Rules enable systems to automatically execute operations, but who has permission to execute what? Data security is Palantir's foundation. Next, we will dive deep into Palantir's multi-layered security model: from military-grade information compartmentalization to fine-grained row-and-column-level access control, revealing why the world's most sensitive organizations trust Palantir with their most classified data.
#palantir #actions #rules #functions #automation #ontology #coomia-dip #closed-loop