Skip to content

Your first intent

This guide walks through building a Create Calendar Event intent from scratch — all the way from empty file to production Swift. By the end you’ll understand defineIntent, the param.* helpers, entitlements, and Info.plist keys.

The goal

We want Siri to be able to say:

“Hey Siri, create a calendar event called ‘Dentist’ tomorrow at 2pm for 30 minutes.”

That means our intent needs:

  • A title and description (shown in Shortcuts)
  • A domain — we’ll use productivity
  • Four parameters: title, start date, duration, and an “all day” flag
  • The calendars entitlement so iOS actually lets us write to EventKit
  • An Info.plist key so Siri can ask for calendar permission

Write it

Create a file at intents/CreateCalendarEvent.intent.ts:

intents/CreateCalendarEvent.intent.ts
import { defineIntent, param } from "@axint/compiler/sdk";
export default defineIntent({
name: "CreateCalendarEventIntent",
title: "Create Calendar Event",
description: "Creates a new event on the user's calendar.",
domain: "productivity",
params: {
eventTitle: param.string("Title of the event"),
startDate: param.date("When the event starts"),
durationMinutes: param.int("Length of the event in minutes"),
isAllDay: param.boolean("Whether the event is all-day", {
optional: true,
default: false,
}),
},
entitlements: ["com.apple.developer.calendars"],
infoPlistKeys: ["NSCalendarsUsageDescription"],
});

Compile it

Terminal window
axint compile intents/CreateCalendarEvent.intent.ts \
--out ios/Intents/CreateCalendarEventIntent.swift \
--emit-info-plist \
--emit-entitlements \
--sandbox \
--format

You get three files:

FileWhat it is
CreateCalendarEventIntent.swiftThe compiled Swift intent
CreateCalendarEventIntent.plist.fragment.xml<key>/<string> pairs to merge into your Info.plist
CreateCalendarEventIntent.entitlements.fragment.xmlEntitlement dictionary to merge into your .entitlements

What the Swift looks like

import AppIntents
import Foundation
struct CreateCalendarEventIntent: AppIntent {
static var title: LocalizedStringResource = "Create Calendar Event"
static var description = IntentDescription(
"Creates a new event on the user's calendar."
)
@Parameter(title: "Title of the event")
var eventTitle: String
@Parameter(title: "When the event starts")
var startDate: Date
@Parameter(title: "Length of the event in minutes")
var durationMinutes: Int
@Parameter(title: "Whether the event is all-day", default: false)
var isAllDay: Bool
func perform() async throws -> some IntentResult {
// TODO: call EventKit to actually create the event
return .result()
}
}

Note how:

  • param.int mapped to Swift Int (not Double or NSNumber)
  • The optional isAllDay parameter got a real Swift default: false
  • The description shows up as a LocalizedStringResource for free localization

Fill in perform()

Axint generates the shape of perform() but deliberately leaves the body empty — you plug into EventKit, HealthKit, HomeKit, or your custom app logic however you like.

func perform() async throws -> some IntentResult {
let store = EKEventStore()
try await store.requestFullAccessToEvents()
let event = EKEvent(eventStore: store)
event.title = eventTitle
event.startDate = startDate
event.endDate = startDate.addingTimeInterval(Double(durationMinutes) * 60)
event.isAllDay = isAllDay
event.calendar = store.defaultCalendarForNewEvents
try store.save(event, span: .thisEvent)
return .result()
}

Next steps