Quickstart
From zero to an agent whose tool calls flow through Klent in five minutes.
This guide builds the minimum integration that gives you the three things Klent exists for: a logged execution, a policy-evaluated action, and a timeline you can inspect.
By the end you will have:
- Started an execution — a session of agent activity.
- Evaluated an action — a tool call — against your policies.
- Logged the outcome as an event on the execution timeline.
You should have completed Install first.
Step 1 — Start an execution
An execution is the parent container for everything a single agent run does. Create one before any tool call.
import { KlentClient } from '@klent/sdk';
const klent = new KlentClient({ apiKey: process.env.KLENT_API_KEY! });
const execution = await klent.startExecution({
agent_id: 'support-agent',
metadata: { user_id: 'u_123', tenant: 'acme' },
});from klent_sdk import KlentClient
klent = KlentClient(api_key=os.environ["KLENT_API_KEY"])
execution = klent.start_execution({
"agent_id": "support-agent",
"metadata": {"user_id": "u_123", "tenant": "acme"},
})The returned execution.id is how you tie every subsequent event and action back to this
particular run. Pass it through your call stack — it is the correlation key.
Step 2 — Evaluate before you act
When your agent decides to call a tool, do not execute it yet. Ask Klent first:
const decision = await klent.evaluateAction({
execution_id: execution.id,
tool: 'send_email',
input: { to: user.email, subject: 'Refund issued', body: '...' },
});
if (decision.decision === 'deny') {
// Surface the reason back to the LLM or fail the turn.
throw new Error(`Blocked by policy: ${decision.reason}`);
}
if (decision.decision === 'modify') {
// Apply the suggested modifications to the input before executing.
// (Modifications are described in docs/concepts/policy-engine.)
}
// decision.decision === 'allow' — safe to proceed
await sendEmail(input);decision = klent.evaluate_action({
"execution_id": execution["id"],
"tool": "send_email",
"input": {"to": user.email, "subject": "Refund issued", "body": "..."},
})
if decision["decision"] == "deny":
raise RuntimeError(f"Blocked by policy: {decision['reason']}")
# decision['decision'] == 'allow' — safe to proceed
send_email(input)evaluateAction is synchronous and returns in a few milliseconds. It also writes a
decision or action_blocked event to the execution timeline automatically — you do not
have to log it yourself.
Step 3 — Log the outcome
After the tool runs (or fails), record what actually happened:
klent.logEvent({
execution_id: execution.id,
type: 'action_executed',
payload: { tool: 'send_email', to: user.email },
});klent.log_event({
"execution_id": execution["id"],
"type": "action_executed",
"payload": {"tool": "send_email", "to": user.email},
})logEvent is non-blocking. Events are buffered and flushed in batches, and on process
exit the SDK flushes once more. You do not need to await it.
If the tool throws, log it as an error:
klent.logEvent({
execution_id: execution.id,
type: 'error',
payload: { tool: 'send_email', message: err.message, stack: err.stack },
});Step 4 — Check the dashboard
Open the execution in the dashboard (/executions/<execution_id>) and you should see
the timeline:
decision(fromevaluateAction)action_executed(fromlogEvent)
That is the full observability loop.
Next
- Write your first policy — stop an action before it happens.
- Architecture — see where Klent fits in your stack.
- Policy engine — operators, effects, evaluation order.