Agent Modes: Dry runs
● Intermediate3 min
kavach run --dry-run runs a program without making any capability call, and answers each one with a made-up value.
kavach run --dry-run refunds.kav
type PayError = Declined | Denied(reason: String)
type Receipt {
id: String
}
capability Payments {
fn refund(order: Int, amount: Int) -> Receipt ! PayError
}
type Bank: Payments {
fn refund(self, order: Int, amount: Int) -> Receipt ! PayError {
print("the bank moves real money here")
Receipt(id: "r{order}")
}
}
agent Refunder {
can Payments.refund, Console
limit Payments.refund {
amount <= 500
}
on refund(order: Int, amount: Int) ! PayError {
const receipt = try Payments.refund(order, amount)
print("order {order}: receipt {receipt.id}")
}
}
fn main() {
const bot = Refunder.start(Payments: Bank())
bot.refund(1, 400) catch e => print("refused: {e}")
bot.refund(2, 900) catch e => print("refused: {e}")
}The program ran and printed:
kavach run dry-refund.kav
order 1: receipt ofry refused: Denied(reason: "limit broken: amount <= 500")[dry run] Payments.refund(order: 1, amount: 400) -> Receipt(id: "ofry ")[dry run] Payments.refund(order: 2, amount: 900) refused: limit broken: amount <= 500
- The bank's code never ran: no
the bank moves real money hereline. - The refund got a made-up
Receipt, generated from its type. The same seed gives the same values every run. - Limits and approvals are still checked: the 900 refund fails as it would for real, and its
[dry run]line saysrefusedand why. askis answered the same way, so no model is called and nothing costs.
Each [dry run] line goes to the error output, apart from what the program prints. These pages show them after the program's own lines.