# @procedure

## Overview

The `@procedure` decorator is used to denote a method within a Book class as a procedure. This links a method to a specific [procedure](/legacy/legacy-experience/books/custom-books/api-reference/procedures.md) in the Kognitos platform.

## Syntax

```python
@procedure(name: str, **kwargs)
```

### Guidelines

**1. Naming Conventions**

Names must begin with **to**. This defines the action or intent of the procedure. For example:

* `@procedure("to capitalize a (string)"`
* `@procedure("to get the (current temperature)")`
* `@procedure("to send an *SMS* message")`

**2. Output Concepts**

[Output concepts](/legacy/legacy-experience/books/custom-books/api-reference/concepts.md) are wrapped in parentheses `()`. For example:

```python
@procedure("to capitalize a (string)")
```

**3. Proper Nouns**

Proper nouns are wrapped between asterisks `**`. For example:

```python
@procedure("to get some (users) from *office365*")
```

In this example, `office365` is considered a proper noun. The procedure is referred to as 'get some users from office365' rather than `the office365`.

## Parameters

<table><thead><tr><th width="133.78515625">Parameter</th><th width="86.625">Type</th><th width="110.99609375">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>name</code></td><td><code>str</code></td><td>Yes</td><td>A description that reflects the action or purpose of the procedure. See the syntax <a href="#guidelines">guidelines</a> for details.</td></tr></tbody></table>

## Keyword Arguments

<table><thead><tr><th width="231.88671875">Argument</th><th width="107.39453125">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>connection_required</code></td><td><code>bool</code></td><td>A boolean that indicates whether a connection to the service is required to execute the procedure. If not specified, it defaults to <code>None</code>.</td></tr><tr><td><code>noun_phrase</code></td><td><code>str</code></td><td>A string that represents the noun phrase for the procedure.</td></tr></tbody></table>

## Examples

### 1. Capitalizing a String

This method implements a procedure that capitalizes a string with one input concept and one output concept.

```python
@procedure("to capitalize a (string)", connection_required=False)
def capitalize_string(self, string: str) -> str:
  """
  Capitalizes the input string.

  Input Concepts:
    the string: The string value you want to capitalize.

  Output Concepts:
    the string: The capitalized string.

  Example 1:
    Capitalize the string "hello"

    >>> capitalize "hello"

  """
  return string.capitalize()
```

### 2. Creating an Order in Truckmate

This method implements a procedure that creates an order in Truckmate. It has one input concept and two output concepts.

```python
@procedure("to create an order in truckmate and get the order number and the bill number")
def create_order(self, order: OrderRequestConcept) -> Tuple[int, str]:
    """
    Create a new order in Truckmate.

    Input Concepts:
        the order: The Truckmate order request (acc to openAPI spec)

    Output Concepts:
        the order number: Order ID of the created order
        the bill number: Bill Number of the created order

    Raises:
        ValueError: If the order is not created successfully.

    Example 1:
        Create the order in Truckmate
        >>> create a json
        >>> use the above as the order
        >>> set the order's id to 1234
        >>> set the order's title to "Awesome title"
        >>> set order's body to "This is the body"
        >>> create the order in truckmate and get the order number and bill number
    """
    logger.info("Creating Order in Truckmate")
    post_body = OrdersPostRequest(orders=[order])
    response = post_orders.sync_detailed(
        client=self._client,
        body=post_body,
    )
    if response.status_code == 201:
        orders_response = response.parsed.to_dict()  # type: ignore
        if orders_response.get("orders"):
            order = orders_response.get("orders")[0]  # type: ignore
            return order.get("orderId"), order.get("billNumber")

    error_response = response.parsed.to_dict()  # type: ignore
    logger.error(
        "Error while creating order in truckmate:  %s",
        error_response.get("errorText"),
    )
    raise ValueError(error_response)
```

### 3. Reading SMS messages using the Twilio API

The following method implements a procedure that reads SMS messages using the Twilio API. In this example, `SMS` is a proper noun.

```python
@procedure("to read some (*SMS* messages)")
def read_sms_messages(
    self,
    offset: Optional[int],
    limit: Optional[int],
    filter_expression: Optional[FilterExpression],
) -> List[SMSMessage]:
    """
    Read some SMS messages using the Twilio API.

    Returns:
        A list of SMS messages that matches the specified filtering criteria

    Example 1:
        Retrieve SMS messages filtered by sender and recipient numbers

        >>> read some sms messages whose sender number is "+18004445555" and whose recipient number is "+18004446666"

    Example 2:
        Retrieve SMS messages filtered by the date in which they were sent

        >>> convert "2022-03-01T15:00:00Z" to a datetime
        >>> use the above as the message date
        >>> read some sms messages whose date sent is the message date

    Example 3:
        Retrieve SMS messages that were sent in the specified time period

        >>> convert "2022-03-01T15:00:00Z" to a datetime
        >>> use the above as the start date
        >>> convert "2022-03-03T15:00:00Z" to a datetime
        >>> use the above as the end date
        >>> read some sms messages whose date sent is after the start date and whose date sent is before the end date
    """
    client = Client(self._account_sid, self._auth_token)

    filter_visitor = SMSMessageFilter()

    if filter_expression is not None:
        filter_expression.accept(filter_visitor)

    messages = client.messages.list(
        to=filter_visitor.recipient_number,
        from_=filter_visitor.sender_number,
        date_sent=filter_visitor.date_sent,
        date_sent_before=filter_visitor.date_sent_before,
        date_sent_after=filter_visitor.date_sent_after,
    )

    if offset is not None:
        messages = messages[offset:]

    if limit is not None:
        messages = messages[:limit]

    return [SMSMessage.from_message_instance(message) for message in messages]
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.kognitos.com/legacy/legacy-experience/books/custom-books/api-reference/decorators/procedure-decorator.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
