Questions

Learn how to implement questions in a BDK Book.

Overview

In your Book, you may need to ask the user for information. For example, if the Book needs to know when a project should begin, it can ask the user, “What is the project start date?” Or if it needs a username, it can prompt the user with, “What is the username?”

When this happens, Kognitos surfaces a question to pause the automation and ask the user for information. A question is an exception that signals that the automation cannot move forward without user input. The BDK provides an easy way to add and handle questions in your Book using the ask() method.

How It Works

The ask() function in the BDK is used to ask a question. Here’s how it works:

1

ask() is Called

ask() is called inside a procedure to ask a question.

2

Kognitos Checks for an Answer

Each time ask() is called, Kognitos checks internally whether it has already stored an answer for that specific question before.

  • If the answer to the question exists, ask() returns the answer value itself.

  • If the answer to the question does not exist, ask() returns a Question.

3

Question is Surfaced (if the answer is not present)

When a Question object is returned from a procedure, Kognitos will:

  1. Forward the question to the user

  2. Pause the automation and wait for a response

  3. Store the answer internally

  4. Restart the procedure from the beginning automatically

    • The second time the procedure runs, ask() will be able to return the answer instead of a Question.

Note: Kognitos only surfaces a question if it doesn’t have the answer stored internally. By remembering answers, it ensures the same questions aren’t unnecessarily presented to the user.

Usage

ask(concept_name: NounPhrasesStringLiteral, concept_type: Type[T], text: Optional[str] = None, choices: Optional[List[T]] = None) -> Union[T, Question[NounPhrasesStringLiteral, T]]
Parameter
Required
Description

concept_name

Yes

The unique name of the concept being asked for.

concept_type

Yes

The return type of the answer.

text

No

(Optional) A message to show the user when the question is prompted in Kognitos.

choices

No

(Optional) A list of predefined options the user can choose from.

To use ask() in your Book, follow these steps:

1

Import

Start by importing the ask() function and Question type from the BDK API:

from kognitos.bdk.api.questions import ask, Question
2

Call ask()

Call the ask() function inside a method decorated with @procedure.

Provide the concept_name (the unique name of the concept being asked for) and the concept_type (the return type of the answer).

result = ask("project start date", str)

(Optional) Specifying the Question Text

You can specify a text to present to the user when the question is prompted in Kognitos. If the text is not specified, questions are presented as Please provide the <concept_name> by default. For example:

result = ask("project start date", str, text="What is the start date of the project?")

(Optional) Specifying Choices

You can also guide users to select an answer from a predefined list by passing a choices argument. When choices are set, Kognitos displays the question with a dropdown menu for the user to select from. For example:

result = ask("project start date", str, choices=["2025-07-22", "2025-07-25", "2025-07-28"])
3

Handle the Result of ask()

The ask() function can return either the answer or a Question object. To handle both cases, explicitly check the return type:

  • If ask() returns a value, that means the answer already exists internally.

  • If ask() returns a Question, that means the answer does not exist internally. What you do with the Question is up to you — the Book can return it, hold onto it for later, or ignore it entirely. If you want Kognitos to surface the question to the user, return the Question object from the procedure. For example:

if isinstance(result := ask("project start date", str), Question)
    return result
4

Use the Answer

Once the ask() function returns a value (and not a Question), you can use the answer just like any other variable in Python — in calculations, conditions, etc. For example:

if isinstance(start_date := ask("project start date", str), Question):
    return start_date

# Use the answer as a datetime object
date_obj = datetime.strptime(date_str, "%Y-%m-%d")
project_due_date = date_obj + timedelta(days=30)
5

Declare Return Types

Always include return types in your procedure definitions. If your procedure may trigger a Question, the return type must reflect that so the system understands which concept(s) you may be asking for. Make sure to include both the concept name (as a string Literal in nounphrase form) and the concept type in the type hint. For example:

@procedure("to get a project due (date)")
def get_due_date(self) -> str | Question[Literal["project start date"], str]:

Examples

1. Asking a Question with Different Return Types

This example shows how to use ask() with a set of mixed-type choices: a string, a datetime, and a float. The return type allows for any of those types, and also accounts for the case where a Question is returned.

@procedure("to get a (value)")
def get_value(self) -> str | datetime | float | Question[Literal["value"], str | datetime | float]:

    choices = ["Hello!", datetime(2023, 1, 1, tzinfo=timezone.utc), 123.456]
    if isinstance(answer := ask("value", Union[str, datetime, float], choices=choices), Question):
        return answer
    return answer

2. Asking Multiple Questions

Sometimes your Book may need to collect more than one piece of information. You can call ask() multiple times in the same procedure. Here’s an example:

from typing import Literal
from kognitos import procedure
from kognitos.bdk.api.questions import ask, Question

@procedure("to get a (text)")
def get_text(self) -> str | Question[Literal["color"], str] | Question[Literal["elephant's name"], str]:
    """
    Get a text
    """
    # First: Ask the user to pick a color
    if isinstance(answer := ask("color", str, text="Pick a color", choices=["red", "blue", "green"]), Question):
        return answer
    color = answer

    # Second: Ask for the elephant's name
    if isinstance(answer := ask("elephant's name", str, text="What is the elephant's name?"), Question):
        return answer
    name = answer

    # You can now use both answers
    return f"The elephant named {name} is painted {color}."

How This Works

  1. The first call to ask() checks whether the answer for color is present.

    1. If not, it returns a Question.

    2. If answered, it stores the value and restarts the procedure.

  2. Now that the answer for color is present, the procedure checks for the elephant’s name.

    1. If not, it returns a Question.

    2. If answered, it stores the value and restarts the procedure.

  3. Once both values are available, the final result is returned.

Last updated

Was this helpful?