Bixby Developer Center

Guides
References

Profile (viv.self)

The viv.self capsule provides access to information in the user's profile, such as given names, phone numbers, and addresses.

Usage

  1. Import this capsule in your capsule.bxb file:

    capsule-imports {
    import (viv.self) {
    as (self)
    version (4.0.3) // always check current version!
    }
    ...
    }

    Always use the current version of viv.self.

  2. In your capsule.bxb file, declare the profile library-permission necessary to access profile information.

    capsule {
    permissions {
    library-permission (self:profile)
    ...
    }
    }
  3. Add localized justifications for the permission in your capsule-info.bxb file(s). This is a text string shown to the user when Bixby first requests access to the profile information. See requested-permissions for more details.

    capsule-info {
    requested-permissions {
    permission (self:profile) {
    justification (MyGreatCapsule needs access to your profile information.)
    }
    }
    ...
    }

Models

Types are always in the viv.* namespace, and in the viv.self.* namespace unless another namespace is specified (e.g., bixby.contact.*). All properties have a cardinality of min (Optional), max (One) unless otherwise specified.

Profile

The Profile structure is a snapshot of the Self structure, and is the recommended way to interact with viv.self. Use the GetProfile action to retrieve a user profile.

PropertyTypeKindNotes
structuredNameStructuredNamestructure(1)
firstNameFirstNametext
lastNameLastNametext
emailInfoEmailInfostructure
phoneInfoPhoneInfostructure
addressInfoAddressInfostructure
  1. The StructuredName is the contact's full name, incorporating the filled-in fields for FirstName and LastName.

Self

The Self structure is modeled after bixby.contact.ContactInfo. However, the structure is not interchangeable with ContactInfo.

PropertyTypeKindNotes
nameInfoNameInfostructure
addressInfosAddressInfostructuremax (Many)
phoneInfosPhoneInfostructuremax (Many)
emailInfosEmailInfostructuremax (Many)
workInfoWorkInfostructure
birthdayInfoBirthdayInfostructure
genderGendername 

NameInfo

This contains properties for the components of the contact's name.

PropertyTypeKindNotes
structuredNameStructuredNametext
firstNameFirstNametext
lastNameLastNametext
displayNameDisplayNametext 

The StructuredName is the contact's full name, incorporating the filled-in fields for FirstName and LastName.

AddressInfo

This contains information about a contact's address. Most of the information is in an UnresolvedAddress structure (see below).

PropertyTypeKindNotes
typeAddressTypeenum(1)
labelAddressLabeltext
addressAddressstructure(2)
  1. The possible symbols for AddressType are Home, Work, and Other.
  2. This structure extends viv.geo.UnresolvedAddress.

PhoneInfo

PropertyTypeKindNotes
phoneTypePhoneTypeenum(1)
phoneNumberPhoneNumbertext(2)
  1. The possible symbols for PhoneType are Mobile, Home, Work, WorkFax, HomeFax, Pager, Callback, Custom, and Other.
  2. This should be a valid phone number. This property is required.

EmailInfo

This contains information about a contact's email address.

PropertyTypeKindNotes
typeEmailTypeenum(1)
addressEmailAddresstextRequired
  1. The possible symbols for EmailType are Home, Work, Other, and Custom. This property is required.
  2. Set to true if this is the contact's default email address.

WorkInfo

PropertyTypeKindNotes
titleTitlename
departmentDepartmentname
companyCompanyname 

BirthdayInfo

This concept extends viv.time.Date.

Field

This is a primitive used for training. It enumerates symbols in the Profile model. The viv.self library includes vocabulary terms to refer to individual fields.

enum (Field) {
symbol (firstName)
symbol (lastName)
symbol (structuredName)
symbol (firstAndLastName)
symbol (phoneInfo)
symbol (emailInfo)
symbol (addressInfo)
}

These symbols have defined vocabulary terms:

vocab (Field) {
"FirstName" { "first name" "given name" }
"LastName" { "last name" "family name" }
"EmailInfo" { "email" "email address" }
"PhoneInfo" { "phone number" "number" "phone" }
"AddressInfo" { "address" }
}

StructuredName and FirstAndLastName have no set vocabulary; capsules that import viv.self can add their own vocabulary to cover those cases, as those might be domain-specific. For details, read about Imported Vocabulary.

Imaginary

This is a primitive used for testing. It is a boolean which can be set to true and passed to the GetProfile action below. If true, then GetProfile will return an "imaginary" profile consisting of mock data rather than the user's actual profile information. See Testing with Imaginary.

Actions

As with other library capsules, most actions are selected by Bixby when it builds the execution graph, rather than needing to be chosen explicitly.

GetProfile

The recommended way to retrieve profile information is to use the GetProfile action. This action prompts the user for any required profile fields you need in your capsule. The profile elicitation views are defined in the profile capsule and can handle hands-free mode.

It is recommended you rely on the views in the profile capsule for profile input prompts instead of customizing the views in your capsule.

action (WhoAmI) {
type (Constructor)
collect {
input (profile) {
min (Required)
type (self.Profile)
default-init {
intent {
goal: self.GetProfile
value-set: self.RequiredField {
self.RequiredField (structuredName)
self.RequiredField (addressInfo)
self.RequiredField (emailInfo)
self.RequiredField (phoneInfo)
}
}
}
}
}
output (MyInfo) {
evaluate {
MyInfo$expr(profile)
}
}
}

In this example, MyInfo has the role-of self.Profile:

structure (MyInfo) {
role-of (self.Profile)
}

Passing Profile to Your Action

To use Profile as an input to one of your capsule's actions, define a constructor action that returns a capsule-specific concept that extends Profile. For a example, a shopping capsule might have a Buyer structure concept:

structure (Buyer) {
role-of (self.Profile)
}

Your capsule can then use Buyer in an input action and initialize it with the fields you require:

action (CreateOrder) {
type (BeginTransaction)

collect {
input (buyer) {
type (Buyer) // buyer is fetched from profile
min (Required)
default-init {
intent {
goal: self.GetProfile
value-set: self.RequiredField {
self.RequiredField (firstName)
self.RequiredField (lastName)
self.RequiredField (addressInfo)
self.RequiredField (emailInfo)
self.RequiredField (phoneInfo)
}
}
}
}
input (product) {
type (Product)
min (Required)
}
}
// Order is a structure with transaction feature that has buyer and
// product properties
output (Order)
}

Testing with Imaginary

When you add self.Imaginary (true) as the value for a GetProfile goal, then the action will return a profile with mock data rather than the user's actual profile. This is used in the CreateOrder action of the Space Resorts sample capsule:

action (CreateOrder) {
description (Create order)
type (BeginTransaction)
collect {

input (item) {
type (Item)
min (Required)
}

input (buyer) {
type (Buyer)
min (Required)
default-init {
intent {
goal: self.GetProfile
value: self.Imaginary(true)
value-set: self.RequiredField {
self.RequiredField(firstName)
self.RequiredField(lastName)
self.RequiredField(emailInfo)
self.RequiredField(phoneInfo)
}
}
}
}

}
output (Order)
}

View on GitHub

This is almost identical to the example given above for GetProfile, but instead of the intent specifying a value-set of required fields, it specifies the imaginary profile.

The imaginary profile is useful for testing purposes:

  • The imaginary profile is guaranteed to be complete, with two sets of phone numbers (mobile and work), emails (home and work), and addresses (home and work).
  • The imaginary profile is always the same. If multiple people are developing and testing your capsule, they'll all be working with the same data.
  • No permissions are required to use the imaginary profile.

Updating Information

To update information drawn from the Profile object in your capsule-specific object, you can pass in the current information and a list of fields that need to be updated.

Note

This example updates the information being used in your capsule, but does not modify the user's actual saved contact information.

action (UpdateBuyer) {
description (Prompt user to enter personal data)
type (Constructor)
collect {
//Order is a structure with transaction feature that has the current buyer and product properties
input (order) {
type (Order)
min (Required)
}
//This is the list of the buyer fields which user wants to update
input (fieldsToUpdate) {
type (self.Field)
min (Required) max (Many)
default-init {
intent {
goal-set: self.Field {
self.Field(firstName)
self.Field(lastName)
self.Field(emailInfo)
self.Field(phoneInfo)
}
}
}
}
//new value for first name
input (firstName) {
type (self.FirstName)
min (Optional) max (One)
}
//new value for last name
input (lastName) {
type (self.LastName)
min (Optional) max (One)
}
//new value for email address
input (emailAddress) {
type (self.EmailAddress)
min (Optional) max (One)
}
//new value for phone number
input (phoneNumber) {
type (self.PhoneNumber)
min (Optional) max (One)
}
input (forcePrompt) {
type (self.ForcePrompt)
min (Optional) max (One)
}
//compute the new buyer information by calling self library
computed-input (buyer) {
type (Buyer)
min (Required)
compute {
intent {
goal: self.GetProfile
value: self.Profile$expr(order.buyer)
value: $expr(firstName)
value: $expr(lastName)
value: $expr(emailAddress)
value: $expr(phoneNumber)
value: $expr(forcePrompt)
subplan {
goal: self.RequiredField
value: $expr(fieldsToUpdate)
}
}
}
}
}
output (Buyer) {
evaluate { $expr(buyer) }
}
}

View on GitHub

To make this work you also need an action such as UpdateOrder:

action (UpdateOrder) {
description (Update order)
type (UpdateTransaction)
collect {
input (order) {
type (Order)
min (Required)
}
input (changedItem) {
type (ChangedItem)
}
input (buyer) {
type (Buyer)
}
}
output (Order)
}

View on GitHub

Constructing a NamedPoint

A useful provided action is ConstructNamedPointFromSelf, which converts a physical address in the user's profile to a Named Point. This action might be used, for example, by a ride sharing app to find a destination in the user's profile.

action (FindProfileDestination) {
type (Search)
collect {
// addressType is passed in from training
input (addressType) {
type (self.AddressType)
min (Required) max (One)
}
// self can be computed rather than explicitly passed
computed-input (self) {
type (self.Self)
min (Optional) max (One)
compute {
intent {
goal: self.Self
route: self.GetSelf
}
}
}
// DestinationPoint is a capsule-specific extension of geo.NamedPoint.
// We compute it with a subplan that uses ConstructNamedPointFromSelf
computed-input (namedPoint) {
type (DestinationPoint)
min (Optional) max (One)
compute {
intent {
goal: DestinationPoint
subplan {
goal: self.ConstructNamedPointFromSelf
subplan {
goal: self.FindAddress
value: $expr(addressType)
value: $expr($self)
}
}
}
}
}
}

output (DestinationPoint) {
...
}
}

This uses several actions within viv.self. Both ConstructNamedPointFromSelf and FindAddress have the same inputs:

InputTypeNotes
addressTypeAddressType
selfSelf 

The GetSelf action has no inputs, and simply returns the Self concept.

Training

Most commonly, your capsules will need to be trained on the AddressType, EmailType, and PhoneType enums, to handle utterances such as "call my office" or "book me a car to go home". A ride sharing capsule might have training such as:

[g:viv.rideshare.RideShare#book] I want a car to go (home)[v:viv.self.AddressType:home]

[g:viv.rideshare.RideShare#book] Book a ride to the (office)[v:viv.self.AddressType:work]